123
This commit is contained in:
893
CryCommon/TArrays.h
Normal file
893
CryCommon/TArrays.h
Normal file
@@ -0,0 +1,893 @@
|
||||
#ifndef _CRY_COMMON_TARRAYS_HDR_
|
||||
#define _CRY_COMMON_TARRAYS_HDR_
|
||||
|
||||
#include "platform.h"
|
||||
#if !defined(LINUX)
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
#include "TAlloc.h"
|
||||
|
||||
template <typename T>
|
||||
void TSimpleSwap (T& a, T& b)
|
||||
{
|
||||
T t = a;
|
||||
a = b;
|
||||
b = t;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// a class with STL naming conventions, incapsulating just a pointer.
|
||||
// it mimics the std::vector with a few methods, but the class doesn't know
|
||||
// about the array size and lacks most of the vector functionality.
|
||||
// WHAT IT IS FOR:
|
||||
// If you need an array that you know the size for, use this.
|
||||
// If you need a local dynamic array that will self-deallocate when out of scope of the function, use this.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, class A = TSimpleAllocator<T> >
|
||||
class TElementaryArray
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef const T & const_reference;
|
||||
typedef T* iterator;
|
||||
typedef const T* const_iterator;
|
||||
|
||||
TElementaryArray (const char* szParentObject, int nParentIndex = 0):
|
||||
m_Allocator(szParentObject, nParentIndex),
|
||||
m_pData (NULL)
|
||||
{
|
||||
#if defined(_DEBUG) && defined(_INC_CRTDBG)
|
||||
m_nSize = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
TElementaryArray (size_t numElements)
|
||||
#if defined(_DEBUG) && defined(_INC_CRTDBG)
|
||||
:m_Allocator("TElementaryArray(n)",1),
|
||||
m_nSize(numElements)
|
||||
#endif
|
||||
{
|
||||
m_pData = numElements?m_Allocator.allocate_construct(numElements):NULL;
|
||||
}
|
||||
|
||||
TElementaryArray ():
|
||||
m_pData (NULL)
|
||||
#if defined(_DEBUG) && defined(_INC_CRTDBG)
|
||||
,m_Allocator("TElementaryArray()",2)
|
||||
,m_nSize(0)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
// copy constructor: impossible since the number of elements is unknown
|
||||
TElementaryArray (const TElementaryArray<T,A>& that):
|
||||
m_pData (NULL)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
// assignment is impossible because the size is unknown
|
||||
TElementaryArray<T,A>& operator = (const TElementaryArray<T,A>& src)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
public:
|
||||
~TElementaryArray()
|
||||
{
|
||||
m_Allocator.deallocate_destroy(m_pData);
|
||||
#if defined(_DEBUG) && defined(_INC_CRTDBG)
|
||||
m_pData = (T*)(UINT_PTR)0xFFEEDDCC; // for debug
|
||||
#endif
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return m_pData == 0;
|
||||
}
|
||||
|
||||
// resizes the array, doesn't preserve the contents
|
||||
void reinit (size_t numElements)
|
||||
{
|
||||
clear();
|
||||
if (numElements > 0)
|
||||
{
|
||||
m_pData = m_Allocator.allocate_construct(numElements);
|
||||
#if defined(_DEBUG) && defined(_INC_CRTDBG)
|
||||
m_nSize = numElements;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// resizes the array, doesn't preserve the contents, copies the given value to all the elements
|
||||
void reinit (size_t numElements, const T& element)
|
||||
{
|
||||
reinit(numElements);
|
||||
for (size_t i = 0; i < numElements; ++i)
|
||||
m_pData[i] = element;
|
||||
}
|
||||
|
||||
// swaps this array with the given one
|
||||
void swap (TElementaryArray<T,A>& rRight)
|
||||
{
|
||||
TSimpleSwap (m_pData, rRight.m_pData);
|
||||
#if defined(_DEBUG) && defined(_INC_CRTDBG)
|
||||
TSimpleSwap (m_nSize, rRight.m_nSize);
|
||||
#endif
|
||||
}
|
||||
|
||||
// cleans up the array
|
||||
void clear()
|
||||
{
|
||||
if (m_pData)
|
||||
{
|
||||
m_Allocator.deallocate_destroy(m_pData);
|
||||
m_pData = NULL;
|
||||
#if defined(_DEBUG) && defined(_INC_CRTDBG)
|
||||
m_nSize = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// returns the first element of the array
|
||||
reference front()
|
||||
{
|
||||
assert (!empty());
|
||||
return m_pData[0];
|
||||
}
|
||||
|
||||
// returns the first element of the array
|
||||
const_reference front() const
|
||||
{
|
||||
assert (!empty());
|
||||
return m_pData[0];
|
||||
}
|
||||
|
||||
// returns the begin iterator of the contained sequence
|
||||
// there is no end iterator in this array, if you need one, use std::vector
|
||||
iterator begin()
|
||||
{
|
||||
return m_pData;
|
||||
}
|
||||
|
||||
// returns the begin iterator of the contained sequence
|
||||
// there is no end iterator in this array, if you need one, use std::vector
|
||||
const_iterator begin() const
|
||||
{
|
||||
return m_pData;
|
||||
}
|
||||
|
||||
reference operator [] (size_t i)
|
||||
{
|
||||
// it is unlikely that the array is more than 1 gigabyte long, so check the index for saneness
|
||||
assert (i < 0x40000000 / sizeof(T));
|
||||
#if defined(_DEBUG) && defined(_INC_CRTDBG)
|
||||
assert (i < m_nSize);
|
||||
#endif
|
||||
return m_pData[i];
|
||||
}
|
||||
|
||||
const_reference operator [] (size_t i) const
|
||||
{
|
||||
// it is unlikely that the array is more than 1 gigabyte long, so check the index for saneness
|
||||
assert (i < 0x40000000 / sizeof(T));
|
||||
#if defined(_DEBUG) && defined(_INC_CRTDBG)
|
||||
assert (i < m_nSize);
|
||||
#endif
|
||||
return m_pData[i];
|
||||
}
|
||||
protected:
|
||||
// array of elements, or NULL
|
||||
T* m_pData;
|
||||
|
||||
#if defined(_DEBUG) && defined(_INC_CRTDBG)
|
||||
// the actual size of the array, USE FOR DEBUGGING ONLY
|
||||
size_t m_nSize;
|
||||
#endif
|
||||
A m_Allocator;
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// a class with STL naming conventions of the methods, incapsulating an array of fixed
|
||||
// size. STL naming conventions are for easier transition between this and std::vector.
|
||||
// optimized for one-time construction and long-term usage (minimum memory overhead)
|
||||
// You can reinitialize the array with resize() though, but be careful: it's not fast
|
||||
//
|
||||
// The only advantage over std::vector is that the number of elements allocates is kept
|
||||
// to the minimum, which is optimal in the case of one-time allocation
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, class A = TSimpleAllocator<T> >
|
||||
class TFixedArray
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef T* iterator;
|
||||
typedef const T* const_iterator;
|
||||
|
||||
TFixedArray (const char* szParentObject, int nParentIndex = 0):
|
||||
m_nSize (0),
|
||||
m_pData (NULL),
|
||||
m_Allocator(szParentObject, nParentIndex)
|
||||
{
|
||||
}
|
||||
|
||||
TFixedArray (size_t numElements):
|
||||
m_nSize (numElements)
|
||||
{
|
||||
m_pData = numElements?m_Allocator.allocate_construct(numElements):NULL;
|
||||
}
|
||||
|
||||
TFixedArray ():
|
||||
m_nSize (0),
|
||||
m_pData (NULL)
|
||||
{
|
||||
}
|
||||
|
||||
// copy constructor: full copy implementation
|
||||
template <typename U, typename B>
|
||||
TFixedArray (const TFixedArray<U,B>& that):
|
||||
m_nSize (that.size()),
|
||||
m_Allocator(that.m_Allocator)
|
||||
{
|
||||
m_pData = that.empty() ? NULL : m_Allocator.allocate_construct(that.size());
|
||||
for (size_t i = 0; i < m_nSize; ++i)
|
||||
m_pData[i] = that[i];
|
||||
}
|
||||
|
||||
// copy constructor: full copy implementation
|
||||
TFixedArray (const TFixedArray<T,A>& that):
|
||||
m_nSize (that.size()),
|
||||
m_Allocator(that.m_Allocator)
|
||||
{
|
||||
m_pData = that.empty() ? NULL : m_Allocator.allocate_construct(that.size());
|
||||
for (size_t i = 0; i < m_nSize; ++i)
|
||||
m_pData[i] = that[i];
|
||||
}
|
||||
|
||||
// copy constructor: full copy implementation
|
||||
template <typename U, typename B>
|
||||
TFixedArray (const char* szParentObject, int nParentIndex, const TFixedArray<U,B>& that):
|
||||
m_nSize (that.size()),
|
||||
m_Allocator(szParentObject, nParentIndex)
|
||||
{
|
||||
m_pData = that.empty() ? NULL : m_Allocator.allocate_construct(that.size());
|
||||
for (size_t i = 0; i < m_nSize; ++i)
|
||||
m_pData[i] = that[i];
|
||||
}
|
||||
|
||||
// copy constructor: full copy implementation
|
||||
TFixedArray (const char* szParentObject, int nParentIndex, const TFixedArray<T,A>& that):
|
||||
m_nSize (that.size()),
|
||||
m_Allocator(szParentObject, nParentIndex)
|
||||
{
|
||||
m_pData = that.empty() ? NULL : m_Allocator.allocate_construct(that.size());
|
||||
for (size_t i = 0; i < m_nSize; ++i)
|
||||
m_pData[i] = that[i];
|
||||
}
|
||||
|
||||
// sets the owner on behalf of whom the memory will be allocated
|
||||
void dbgAssignOwner (const char* szParentObject, int nParentIndex = 0)
|
||||
{
|
||||
m_Allocator = A (szParentObject, nParentIndex);
|
||||
}
|
||||
|
||||
template <typename U,typename B>
|
||||
TFixedArray<T,A>& operator = (const TFixedArray<U,B>& src)
|
||||
{
|
||||
reinit (src.size());
|
||||
for (size_t i = 0; i < m_nSize; ++i)
|
||||
m_pData[i] = src[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
TFixedArray<T,A>& operator = (const TFixedArray<T,A>& src)
|
||||
{
|
||||
reinit (src.size());
|
||||
for (size_t i = 0; i < m_nSize; ++i)
|
||||
m_pData[i] = src[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
~TFixedArray ()
|
||||
{
|
||||
m_Allocator.deallocate_destroy(m_pData);
|
||||
#if defined(_DEBUG)
|
||||
m_pData = (T*)0x32323232;
|
||||
m_nSize = 0x43434343;
|
||||
#endif
|
||||
}
|
||||
|
||||
// returns the size of the array (the number of elements)
|
||||
size_t size() const
|
||||
{
|
||||
return m_nSize;
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return m_nSize == 0;
|
||||
}
|
||||
|
||||
// resizes the array, doesn't preserve the contents
|
||||
void reinit (size_t numElements)
|
||||
{
|
||||
clear();
|
||||
if (numElements > 0)
|
||||
m_pData = m_Allocator.allocate_construct (m_nSize = numElements);
|
||||
}
|
||||
|
||||
// resizes the array, doesn't preserve the contents, copies the given value to all the elements
|
||||
void reinit (size_t numElements, const T& element)
|
||||
{
|
||||
reinit(numElements);
|
||||
for (size_t i = 0; i < numElements; ++i)
|
||||
m_pData[i] = element;
|
||||
}
|
||||
|
||||
// swaps this array with the given one
|
||||
void swap (TFixedArray<T,A>& rRight)
|
||||
{
|
||||
TSimpleSwap (m_pData, rRight.m_pData);
|
||||
TSimpleSwap (m_nSize, rRight.m_nSize);
|
||||
}
|
||||
|
||||
// resizes the array, preserves the contents
|
||||
void resize (size_t numElements)
|
||||
{
|
||||
if (numElements != m_nSize)
|
||||
{
|
||||
if (numElements == 0)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
else
|
||||
if (m_nSize == 0)
|
||||
{
|
||||
reinit (numElements);
|
||||
}
|
||||
else
|
||||
if (m_nSize != numElements)
|
||||
{
|
||||
T* pDataNew = m_Allocator.allocate_construct (numElements);
|
||||
size_t numToCopy = numElements < m_nSize?numElements:m_nSize;
|
||||
for (size_t i = 0; i < numToCopy; ++i)
|
||||
pDataNew[i] = m_pData[i];
|
||||
m_Allocator.deallocate_destroy(m_pData);
|
||||
m_pData = pDataNew;
|
||||
m_nSize = numElements;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// resizes the array, preserves the contents, copies the given value to the appended elements
|
||||
void resize (size_t numElements, const T& sample)
|
||||
{
|
||||
size_t i = m_nSize; // remember the old size
|
||||
resize (numElements);
|
||||
// initialize the tail of the array
|
||||
for (;i < numElements;++i)
|
||||
m_pData[i] = sample;
|
||||
}
|
||||
|
||||
// cleans up the array
|
||||
void clear()
|
||||
{
|
||||
m_Allocator.deallocate_destroy(m_pData);
|
||||
m_pData = NULL;
|
||||
m_nSize = 0;
|
||||
}
|
||||
|
||||
// adds the element to the end of the array
|
||||
void push_back (const T& sample)
|
||||
{
|
||||
// add one element, and copy the sample to it
|
||||
resize (size() + 1, sample);
|
||||
}
|
||||
|
||||
// removes the element from the end of the array
|
||||
void pop_back()
|
||||
{
|
||||
if (size() > 0)
|
||||
resize (size()-1);
|
||||
else
|
||||
assert (0);
|
||||
}
|
||||
|
||||
// inserts the element in place of the given iterator
|
||||
void insert (iterator it, const T& element)
|
||||
{
|
||||
assert (it >= begin() && it <= end());
|
||||
insert (it - begin(), element);
|
||||
}
|
||||
|
||||
// inserts the element into the given place in the array\
|
||||
// (inserts before the given element)
|
||||
void insert (size_t nIndex, const T& element)
|
||||
{
|
||||
assert (nIndex <= size());
|
||||
|
||||
T* pData = m_Allocator.allocate_construct (size() + 1);
|
||||
size_t i;
|
||||
// copy the pre-array
|
||||
for (i = 0; i < nIndex; ++i)
|
||||
pData[i] = m_pData[i];
|
||||
assert (i = nIndex);
|
||||
pData[i] = element;
|
||||
// copy the post-array
|
||||
for (; i < m_nSize;++i)
|
||||
pData[i+1] = m_pData[i];
|
||||
// swap the new and old arrays
|
||||
m_Allocator.deallocate_destroy(m_pData);
|
||||
m_pData = pData;
|
||||
++m_nSize;
|
||||
}
|
||||
|
||||
// erases an element at the given position
|
||||
void erase (size_t nIndex)
|
||||
{
|
||||
if (nIndex < size())
|
||||
{
|
||||
if (size() > 1)
|
||||
{
|
||||
T* pData = m_Allocator.allocate_construct(size() - 1);
|
||||
size_t i;
|
||||
// copy the pre-array
|
||||
for (i = 0; i < nIndex; ++i)
|
||||
pData[i] = m_pData[i];
|
||||
assert (i = nIndex);
|
||||
// copy the post-array
|
||||
for (; i < m_nSize-1;++i)
|
||||
pData[i] = m_pData[i+1];
|
||||
// swap the new and old arrays
|
||||
m_Allocator.deallocate_destroy(m_pData);
|
||||
m_pData = pData;
|
||||
--m_nSize;
|
||||
|
||||
}
|
||||
else
|
||||
clear();
|
||||
}
|
||||
}
|
||||
|
||||
// returns the last element of the array
|
||||
reference back()
|
||||
{
|
||||
assert (!empty());
|
||||
return m_pData[m_nSize-1];
|
||||
}
|
||||
|
||||
// returns the last element of the array
|
||||
const_reference back() const
|
||||
{
|
||||
assert (!empty());
|
||||
return m_pData[m_nSize-1];
|
||||
}
|
||||
|
||||
// returns the first element of the array
|
||||
reference front()
|
||||
{
|
||||
assert (!empty());
|
||||
return m_pData[0];
|
||||
}
|
||||
|
||||
// returns the first element of the array
|
||||
const_reference front() const
|
||||
{
|
||||
assert (!empty());
|
||||
return m_pData[0];
|
||||
}
|
||||
|
||||
// returns the begin iterator of the contained sequence
|
||||
iterator begin()
|
||||
{
|
||||
return m_pData;
|
||||
}
|
||||
|
||||
// returns the begin iterator of the contained sequence
|
||||
const_iterator begin() const
|
||||
{
|
||||
return m_pData;
|
||||
}
|
||||
|
||||
// returns the end iterator of the contained sequence
|
||||
iterator end()
|
||||
{
|
||||
return m_pData+m_nSize;
|
||||
}
|
||||
|
||||
// returns the end iterator of the contained sequence
|
||||
const_iterator end() const
|
||||
{
|
||||
return m_pData+m_nSize;
|
||||
}
|
||||
|
||||
reference operator [] (size_t i)
|
||||
{
|
||||
// the i==0 is left here to allow extract the pointer to the 0th element
|
||||
// even when the array is empty. In case index is not 0, it must be < size
|
||||
assert(i == 0 || i < m_nSize);
|
||||
|
||||
return m_pData[i];
|
||||
}
|
||||
|
||||
const_reference operator [] (size_t i) const
|
||||
{
|
||||
// the i==0 is left here to allow extract the pointer to the 0th element
|
||||
// even when the array is empty. In case index is not 0, it must be < size
|
||||
assert(i == 0 || i < m_nSize);
|
||||
|
||||
return m_pData[i];
|
||||
}
|
||||
protected:
|
||||
// array of elements
|
||||
T* m_pData;
|
||||
// number of elements in the array m_pData
|
||||
size_t m_nSize;
|
||||
|
||||
A m_Allocator;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// A class with STL naming conventions
|
||||
// Damped implementation of a resizable array: once the capacity is increased,
|
||||
// it never decreases during normal resizing operations.
|
||||
// The hidden fixed array is used as the storage, and the outer represnetation
|
||||
// of the array size is kept in a separate variable
|
||||
template <typename T, class A = TSimpleAllocator<T> > class TGrowArray : protected TFixedArray<T,A>
|
||||
{
|
||||
public:
|
||||
typedef typename TFixedArray<T,A>::iterator iterator;
|
||||
typedef typename TFixedArray<T,A>::const_iterator const_iterator;
|
||||
typedef typename TFixedArray<T,A>::reference reference;
|
||||
typedef typename TFixedArray<T,A>::const_reference const_reference;
|
||||
|
||||
TGrowArray ():
|
||||
TFixedArray<T,A> ("TGrowArray()", 1),
|
||||
m_nSize(0)
|
||||
{
|
||||
}
|
||||
|
||||
TGrowArray (const char* szParentObject, int nParentIndex = 0):
|
||||
TFixedArray<T,A> (szParentObject, nParentIndex),
|
||||
m_nSize (0)
|
||||
{
|
||||
}
|
||||
|
||||
TGrowArray (int numElements):
|
||||
TFixedArray<T,A>(numElements, "TGrowArray(n)",2),
|
||||
m_nSize (numElements)
|
||||
{
|
||||
}
|
||||
|
||||
// copy constructor: full copy implementation
|
||||
// reserves enough data to contain the whole array
|
||||
template <typename U, typename B>
|
||||
TGrowArray (const TGrowArray<U,B>& that):
|
||||
TFixedArray<T,A>(that),
|
||||
m_nSize (that.size())
|
||||
{
|
||||
}
|
||||
|
||||
// copy constructor: full copy implementation
|
||||
TGrowArray (const TGrowArray<T,A>& that):
|
||||
TFixedArray<T,A>(that),
|
||||
m_nSize (that.size())
|
||||
{
|
||||
}
|
||||
|
||||
// copy constructor: full copy implementation
|
||||
// reserves enough data to contain the whole array
|
||||
template <typename U, typename B>
|
||||
TGrowArray (const char* szParentObject, int nParentIndex, const TGrowArray<U,B>& that):
|
||||
TFixedArray<T,A>(szParentObject, nParentIndex, that),
|
||||
m_nSize (that.size())
|
||||
{
|
||||
}
|
||||
|
||||
// copy constructor: full copy implementation
|
||||
TGrowArray (const char* szParentObject, int nParentIndex, const TGrowArray<T,A>& that):
|
||||
TFixedArray<T,A>(szParentObject, nParentIndex, that),
|
||||
m_nSize (that.size())
|
||||
{
|
||||
}
|
||||
|
||||
template <typename U, typename B>
|
||||
TGrowArray<T,A>& operator = (const TGrowArray<U,B>& src)
|
||||
{
|
||||
reinit (src.size());
|
||||
for (size_t i = 0; i < m_nSize; ++i)
|
||||
this->m_pData[i] = src[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
TGrowArray<T,A>& operator = (const TGrowArray<T,A>& src)
|
||||
{
|
||||
reinit (src.size());
|
||||
for (size_t i = 0; i < m_nSize; ++i)
|
||||
this->m_pData[i] = src[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
~TGrowArray ()
|
||||
{
|
||||
#if defined(_DEBUG) && defined(_INC_CRTDBG)
|
||||
m_nSize = 0x42434243;
|
||||
#endif
|
||||
}
|
||||
|
||||
// returns the size of the array (the number of elements)
|
||||
size_t size() const
|
||||
{
|
||||
return m_nSize;
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return m_nSize == 0;
|
||||
}
|
||||
|
||||
size_t capacity ()const
|
||||
{
|
||||
return TFixedArray<T,A>::size();
|
||||
}
|
||||
|
||||
// this is the algorithm that dampers element reallocations.
|
||||
// given the minimum required number of elements, it returns
|
||||
// some number >= the given so that the next reallocation will not occur immediately
|
||||
// after reaching that number
|
||||
static inline size_t dampNumElements(size_t numElements)
|
||||
{
|
||||
return numElements + (numElements >> 1);
|
||||
}
|
||||
|
||||
// resizes the array, doesn't preserve the contents
|
||||
void reinit (size_t numElements)
|
||||
{
|
||||
if (capacity() < numElements)
|
||||
{
|
||||
TFixedArray<T,A>::reinit (dampNumElements(numElements));
|
||||
}
|
||||
m_nSize = numElements;
|
||||
}
|
||||
|
||||
// resizes the array, doesn't preserve the contents, copies the given value to all the elements
|
||||
void reinit (size_t numElements, const T& element)
|
||||
{
|
||||
reinit(numElements);
|
||||
for (size_t i = 0; i < numElements; ++i)
|
||||
this->m_pData[i] = element;
|
||||
}
|
||||
|
||||
// swaps this array with the given one
|
||||
void swap (TGrowArray<T,A>& rRight)
|
||||
{
|
||||
TFixedArray<T,A>::swap (rRight);
|
||||
TSimpleSwap (m_nSize, rRight.m_nSize);
|
||||
}
|
||||
|
||||
// resizes the array, preserves the contents
|
||||
void resize (size_t numElements)
|
||||
{
|
||||
reserve (numElements);
|
||||
m_nSize = numElements;
|
||||
}
|
||||
|
||||
// resizes the array, preserves the contents, copies the given value to the appended elements
|
||||
void resize (size_t numElements, const T& sample)
|
||||
{
|
||||
size_t i = m_nSize; // remember the old size
|
||||
resize (numElements);
|
||||
// initialize the tail of the array
|
||||
for (;i < numElements;++i)
|
||||
this->m_pData[i] = sample;
|
||||
}
|
||||
|
||||
// adds the element to the end of the array
|
||||
void push_back (const T& sample)
|
||||
{
|
||||
// add one element, and copy the sample to it
|
||||
resize (size() + 1, sample);
|
||||
}
|
||||
|
||||
// deletes the element from the end of the array;
|
||||
// doesn't actually destruct the element as it can be reused
|
||||
void pop_back()
|
||||
{
|
||||
if (m_nSize > 0)
|
||||
--m_nSize;
|
||||
else
|
||||
assert (0);
|
||||
}
|
||||
|
||||
// inserts the element in place of the given iterator
|
||||
void insert (iterator it, const T& element)
|
||||
{
|
||||
assert (it >= begin() && it <= end());
|
||||
insert (it - begin(), element);
|
||||
}
|
||||
|
||||
// inserts the element into the given place in the array\
|
||||
// (inserts before the given element)
|
||||
void insert (size_t nIndex, const T& element)
|
||||
{
|
||||
assert (nIndex <= size());
|
||||
resize (size() + 1);
|
||||
for (size_t i = size()-1; i > nIndex; --i)
|
||||
(*this)[i] = (*this)[i-1];
|
||||
(*this)[nIndex] = element;
|
||||
}
|
||||
|
||||
// erases an element at the given position
|
||||
void erase (iterator it)
|
||||
{
|
||||
assert (it >= begin() && it < end());
|
||||
erase (it - begin());
|
||||
}
|
||||
|
||||
// erases an element at the given position
|
||||
void erase (size_t nIndex)
|
||||
{
|
||||
assert (nIndex < size());
|
||||
for (size_t i = nIndex; i < size()-1; ++i)
|
||||
(*this)[i] = (*this)[i+1];
|
||||
resize (size()-1);
|
||||
}
|
||||
|
||||
|
||||
// makes sure capacity() returns at least the given value
|
||||
// keeps the current contents
|
||||
void reserve (size_t numElements)
|
||||
{
|
||||
if (numElements > capacity())
|
||||
{
|
||||
if (m_nSize)
|
||||
TFixedArray<T,A>::resize (numElements);
|
||||
else
|
||||
TFixedArray<T,A>::reinit (numElements);
|
||||
}
|
||||
}
|
||||
|
||||
// makes sure capacity() returns the same value as size()
|
||||
void shrink ()
|
||||
{
|
||||
assert (capacity() >= size());
|
||||
if (size() == 0)
|
||||
{
|
||||
// clear the reserve
|
||||
TFixedArray<T,A>::clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
// make the reserve exactly the size of this array
|
||||
TFixedArray<T,A>::resize(size());
|
||||
}
|
||||
}
|
||||
|
||||
// cleans up the array
|
||||
void clear()
|
||||
{
|
||||
m_nSize = 0;
|
||||
}
|
||||
|
||||
// reserves at least the given number of elements and resets (clears) the array
|
||||
void reset (size_t numElements)
|
||||
{
|
||||
clear();
|
||||
if (numElements > capacity())
|
||||
TFixedArray<T,A>::reinit (numElements);
|
||||
}
|
||||
|
||||
// returns the last element of the array
|
||||
reference back()
|
||||
{
|
||||
assert (!empty());
|
||||
return this->m_pData[m_nSize-1];
|
||||
}
|
||||
|
||||
// returns the last element of the array
|
||||
const_reference back() const
|
||||
{
|
||||
assert (!empty());
|
||||
return this->m_pData[m_nSize-1];
|
||||
}
|
||||
|
||||
// returns the first element of the array
|
||||
reference front()
|
||||
{
|
||||
assert (!empty());
|
||||
return this->m_pData[0];
|
||||
}
|
||||
|
||||
// returns the first element of the array
|
||||
const_reference front() const
|
||||
{
|
||||
assert (!empty());
|
||||
return this->m_pData[0];
|
||||
}
|
||||
|
||||
// returns the begin iterator of the contained sequence
|
||||
iterator begin()
|
||||
{
|
||||
return this->m_pData;
|
||||
}
|
||||
|
||||
// returns the begin iterator of the contained sequence
|
||||
const_iterator begin() const
|
||||
{
|
||||
return this->m_pData;
|
||||
}
|
||||
|
||||
// returns the end iterator of the contained sequence
|
||||
iterator end()
|
||||
{
|
||||
return this->m_pData+m_nSize;
|
||||
}
|
||||
|
||||
// returns the end iterator of the contained sequence
|
||||
const_iterator end() const
|
||||
{
|
||||
return this->m_pData+m_nSize;
|
||||
}
|
||||
|
||||
reference operator [] (size_t i)
|
||||
{
|
||||
if(this->m_pData)
|
||||
assert(i >= 0 && i < m_nSize);
|
||||
else
|
||||
assert(i==0);
|
||||
|
||||
return this->m_pData[i];
|
||||
}
|
||||
|
||||
const T& operator [] (size_t i) const
|
||||
{
|
||||
if(this->m_pData)
|
||||
assert(i >= 0 && i < m_nSize);
|
||||
else
|
||||
assert(i==0);
|
||||
|
||||
return this->m_pData[i];
|
||||
}
|
||||
protected:
|
||||
// number of elements - as it's seen from the outside
|
||||
size_t m_nSize;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// the follwoing definitions are for auto-declaring getters/setters for
|
||||
// T*Array members
|
||||
// USAGE:
|
||||
// if you have an array std::vector<CryVertex> m_arrMyArray,
|
||||
// then Type is CryVertex, Singular is probably Vertex, Plural is probably Vertices, member is m_arrMyArray
|
||||
|
||||
#define DECLARE_ELEMENTARY_ARRAY_GETTER_METHODS(Type, Singular, Plural, member) \
|
||||
Type* get##Plural() {return member.begin();} \
|
||||
const Type* get##Plural()const {return member.begin();} \
|
||||
Type& get##Singular(unsigned i) {assert (i < num##Plural()); return member[i];} \
|
||||
const Type& get##Singular(unsigned i)const {assert (i < num##Plural()); return member[i];}
|
||||
|
||||
#define DECLARE_PLAIN_ARRAY_GETTER_METHODS(Type, Singular, Plural, member) \
|
||||
Type* get##Plural() {return member;} \
|
||||
const Type* get##Plural()const {return member;} \
|
||||
Type& get##Singular(unsigned i) {assert (i < num##Plural()); return member[i];} \
|
||||
const Type& get##Singular(unsigned i)const {assert (i < num##Plural()); return member[i];} \
|
||||
void set##Singular (unsigned i, const Type& newValue) {assert (i < num##Plural()); member[i] = newValue;}
|
||||
|
||||
|
||||
#define DECLARE_ARRAY_GETTER_METHODS(Type, Singular, Plural, member) \
|
||||
DECLARE_ELEMENTARY_ARRAY_GETTER_METHODS(Type, Singular, Plural, member) \
|
||||
unsigned num##Plural() const{return (unsigned)member.size();}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user