| /*!**************************************************************************** |
| |
| @file PVRTArray.h |
| @copyright Copyright (c) Imagination Technologies Limited. |
| @brief Expanding array template class. Allows appending and direct |
| access. Mixing access methods should be approached with caution. |
| |
| ******************************************************************************/ |
| #ifndef __PVRTARRAY_H__ |
| #define __PVRTARRAY_H__ |
| |
| #include "PVRTGlobal.h" |
| #include "PVRTError.h" |
| |
| /****************************************************************************** |
| ** Classes |
| ******************************************************************************/ |
| |
| /*!*************************************************************************** |
| @class CPVRTArray |
| @brief Expanding array template class. |
| *****************************************************************************/ |
| template<typename T> |
| class CPVRTArray |
| { |
| public: |
| /*!*************************************************************************** |
| @brief Blank constructor. Makes a default sized array. |
| *****************************************************************************/ |
| CPVRTArray() : m_uiSize(0), m_uiCapacity(GetDefaultSize()) |
| { |
| m_pArray = new T[m_uiCapacity]; |
| } |
| |
| /*!*************************************************************************** |
| @brief Constructor taking initial size of array in elements. |
| @param[in] uiSize intial size of array |
| *****************************************************************************/ |
| CPVRTArray(const unsigned int uiSize) : m_uiSize(0), m_uiCapacity(uiSize) |
| { |
| _ASSERT(uiSize != 0); |
| m_pArray = new T[uiSize]; |
| } |
| |
| /*!*************************************************************************** |
| @brief Copy constructor. |
| @param[in] original the other dynamic array |
| *****************************************************************************/ |
| CPVRTArray(const CPVRTArray& original) : m_uiSize(original.m_uiSize), |
| m_uiCapacity(original.m_uiCapacity) |
| { |
| m_pArray = new T[m_uiCapacity]; |
| for(unsigned int i=0;i<m_uiSize;i++) |
| { |
| m_pArray[i]=original.m_pArray[i]; |
| } |
| } |
| |
| /*!*************************************************************************** |
| @brief constructor from ordinary array. |
| @param[in] pArray an ordinary array |
| @param[in] uiSize number of elements passed |
| *****************************************************************************/ |
| CPVRTArray(const T* const pArray, const unsigned int uiSize) : m_uiSize(uiSize), |
| m_uiCapacity(uiSize) |
| { |
| _ASSERT(uiSize != 0); |
| m_pArray = new T[uiSize]; |
| for(unsigned int i=0;i<m_uiSize;i++) |
| { |
| m_pArray[i]=pArray[i]; |
| } |
| } |
| |
| /*!*************************************************************************** |
| @brief constructor from a capacity and initial value. |
| @param[in] uiSize initial capacity |
| @param[in] val value to populate with |
| *****************************************************************************/ |
| CPVRTArray(const unsigned int uiSize, const T& val) : m_uiSize(uiSize), |
| m_uiCapacity(uiSize) |
| { |
| _ASSERT(uiSize != 0); |
| m_pArray = new T[uiSize]; |
| for(unsigned int uiIndex = 0; uiIndex < m_uiSize; ++uiIndex) |
| { |
| m_pArray[uiIndex] = val; |
| } |
| } |
| |
| /*!*************************************************************************** |
| @brief Destructor. |
| *****************************************************************************/ |
| virtual ~CPVRTArray() |
| { |
| if(m_pArray) |
| delete [] m_pArray; |
| } |
| |
| /*!*************************************************************************** |
| @brief Inserts an element into the array, expanding it |
| if necessary. |
| @param[in] pos The position to insert the new element at |
| @param[in] addT The element to insert |
| @return The index of the new item or -1 on failure. |
| *****************************************************************************/ |
| int Insert(const unsigned int pos, const T& addT) |
| { |
| unsigned int uiIndex = pos; |
| |
| if(pos >= m_uiSize) // Are we adding to the end |
| uiIndex = Append(addT); |
| else |
| { |
| unsigned int uiNewCapacity = 0; |
| T* pArray = m_pArray; |
| |
| if(m_uiSize > m_uiCapacity) |
| { |
| uiNewCapacity = m_uiCapacity + 10; // Expand the array by 10. |
| |
| pArray = new T[uiNewCapacity]; // New Array |
| |
| if(!pArray) |
| return -1; // Failed to allocate memory! |
| |
| // Copy the first half to the new array |
| for(unsigned int i = 0; i < pos; ++i) |
| { |
| pArray[i] = m_pArray[i]; |
| } |
| } |
| |
| // Copy last half to the new array |
| for(unsigned int i = m_uiSize; i > pos; --i) |
| { |
| pArray[i] = m_pArray[i - 1]; |
| } |
| |
| // Insert our new element |
| pArray[pos] = addT; |
| uiIndex = pos; |
| |
| // Increase our size |
| ++m_uiSize; |
| |
| // Switch pointers and free memory if needed |
| if(pArray != m_pArray) |
| { |
| m_uiCapacity = uiNewCapacity; |
| delete[] m_pArray; |
| m_pArray = pArray; |
| } |
| } |
| |
| return uiIndex; |
| } |
| |
| /*!*************************************************************************** |
| @brief Appends an element to the end of the array, expanding it |
| if necessary. |
| @param[in] addT The element to append |
| @return The index of the new item. |
| *****************************************************************************/ |
| unsigned int Append(const T& addT) |
| { |
| unsigned int uiIndex = Append(); |
| m_pArray[uiIndex] = addT; |
| return uiIndex; |
| } |
| |
| /*!*************************************************************************** |
| @brief Creates space for a new item, but doesn't add. Instead |
| returns the index of the new item. |
| @return The index of the new item. |
| *****************************************************************************/ |
| unsigned int Append() |
| { |
| unsigned int uiIndex = m_uiSize; |
| SetCapacity(m_uiSize+1); |
| m_uiSize++; |
| |
| return uiIndex; |
| } |
| |
| /*!*************************************************************************** |
| @brief Clears the array. |
| *****************************************************************************/ |
| void Clear() |
| { |
| m_uiSize = 0U; |
| } |
| |
| /*!*************************************************************************** |
| @brief Changes the array to the new size |
| @param[in] uiSize New size of array |
| *****************************************************************************/ |
| EPVRTError Resize(const unsigned int uiSize) |
| { |
| EPVRTError err = SetCapacity(uiSize); |
| |
| if(err != PVR_SUCCESS) |
| return err; |
| |
| m_uiSize = uiSize; |
| return PVR_SUCCESS; |
| } |
| |
| /*!*************************************************************************** |
| @brief Expands array to new capacity |
| @param[in] uiSize New capacity of array |
| *****************************************************************************/ |
| EPVRTError SetCapacity(const unsigned int uiSize) |
| { |
| if(uiSize <= m_uiCapacity) |
| return PVR_SUCCESS; // nothing to be done |
| |
| unsigned int uiNewCapacity; |
| if(uiSize < m_uiCapacity*2) |
| { |
| uiNewCapacity = m_uiCapacity*2; // Ignore the new size. Expand to twice the previous size. |
| } |
| else |
| { |
| uiNewCapacity = uiSize; |
| } |
| |
| T* pNewArray = new T[uiNewCapacity]; // New Array |
| if(!pNewArray) |
| return PVR_FAIL; // Failed to allocate memory! |
| |
| // Copy source data to new array |
| for(unsigned int i = 0; i < m_uiSize; ++i) |
| { |
| pNewArray[i] = m_pArray[i]; |
| } |
| |
| // Switch pointers and free memory |
| m_uiCapacity = uiNewCapacity; |
| T* pOldArray = m_pArray; |
| m_pArray = pNewArray; |
| delete [] pOldArray; |
| return PVR_SUCCESS; |
| } |
| |
| /*!*************************************************************************** |
| @fn Copy |
| @brief A copy function. Will attempt to copy from other CPVRTArrays |
| if this is possible. |
| @param[in] other The CPVRTArray needing copied |
| *****************************************************************************/ |
| template<typename T2> |
| void Copy(const CPVRTArray<T2>& other) |
| { |
| T* pNewArray = new T[other.GetCapacity()]; |
| if(pNewArray) |
| { |
| // Copy data |
| for(unsigned int i = 0; i < other.GetSize(); i++) |
| { |
| pNewArray[i] = other[i]; |
| } |
| |
| // Free current array |
| if(m_pArray) |
| delete [] m_pArray; |
| |
| // Swap pointers |
| m_pArray = pNewArray; |
| |
| m_uiCapacity = other.GetCapacity(); |
| m_uiSize = other.GetSize(); |
| } |
| } |
| |
| /*!*************************************************************************** |
| @brief assignment operator. |
| @param[in] other The CPVRTArray needing copied |
| *****************************************************************************/ |
| CPVRTArray& operator=(const CPVRTArray<T>& other) |
| { |
| if(&other != this) |
| Copy(other); |
| |
| return *this; |
| } |
| |
| /*!*************************************************************************** |
| @brief appends an existing CPVRTArray on to this one. |
| @param[in] other the array to append. |
| *****************************************************************************/ |
| CPVRTArray& operator+=(const CPVRTArray<T>& other) |
| { |
| if(&other != this) |
| { |
| for(unsigned int uiIndex = 0; uiIndex < other.GetSize(); ++uiIndex) |
| { |
| Append(other[uiIndex]); |
| } |
| } |
| |
| return *this; |
| } |
| |
| /*!*************************************************************************** |
| @brief Indexed access into array. Note that this has no error |
| checking whatsoever |
| @param[in] uiIndex index of element in array |
| @return the element indexed |
| *****************************************************************************/ |
| T& operator[](const unsigned int uiIndex) |
| { |
| _ASSERT(uiIndex < m_uiCapacity); |
| return m_pArray[uiIndex]; |
| } |
| |
| /*!*************************************************************************** |
| @brief Indexed access into array. Note that this has no error checking whatsoever |
| @param[in] uiIndex index of element in array |
| @return The element indexed |
| *****************************************************************************/ |
| const T& operator[](const unsigned int uiIndex) const |
| { |
| _ASSERT(uiIndex < m_uiCapacity); |
| return m_pArray[uiIndex]; |
| } |
| |
| /*!*************************************************************************** |
| @return Size of array |
| @brief Gives current size of array/number of elements |
| *****************************************************************************/ |
| unsigned int GetSize() const |
| { |
| return m_uiSize; |
| } |
| |
| /*!*************************************************************************** |
| @brief Gives the default size of array/number of elements |
| @return Default size of array |
| *****************************************************************************/ |
| static unsigned int GetDefaultSize() |
| { |
| return 16U; |
| } |
| |
| /*!*************************************************************************** |
| @brief Gives current allocated size of array/number of elements |
| @return Capacity of array |
| *****************************************************************************/ |
| unsigned int GetCapacity() const |
| { |
| return m_uiCapacity; |
| } |
| |
| /*!*************************************************************************** |
| @brief Indicates whether the given object resides inside the array. |
| @param[in] object The object to check in the array |
| @return true if object is contained in this array. |
| *****************************************************************************/ |
| bool Contains(const T& object) const |
| { |
| for(unsigned int uiIndex = 0; uiIndex < m_uiSize; ++uiIndex) |
| { |
| if(m_pArray[uiIndex] == object) |
| return true; |
| } |
| return false; |
| } |
| |
| /*!*************************************************************************** |
| @brief Attempts to find the object in the array and returns a |
| pointer if it is found, or NULL if not found. The time |
| taken is O(N). |
| @param[in] object The object to check in the array |
| @return Pointer to the found object or NULL. |
| *****************************************************************************/ |
| T* Find(const T& object) const |
| { |
| for(unsigned int uiIndex = 0; uiIndex < m_uiSize; ++uiIndex) |
| { |
| if(m_pArray[uiIndex] == object) |
| return &m_pArray[uiIndex]; |
| } |
| return NULL; |
| } |
| |
| /*!*************************************************************************** |
| @brief Simple bubble-sort of the array. Pred should be an object that |
| defines a bool operator(). |
| @param[in] predicate The object which defines "bool operator()" |
| *****************************************************************************/ |
| template<class Pred> |
| void Sort(Pred predicate) |
| { |
| bool bSwap; |
| for(unsigned int i=0; i < m_uiSize; ++i) |
| { |
| bSwap = false; |
| for(unsigned int j=0; j < m_uiSize-1; ++j) |
| { |
| if(predicate(m_pArray[j], m_pArray[j+1])) |
| { |
| PVRTswap(m_pArray[j], m_pArray[j+1]); |
| bSwap = true; |
| } |
| } |
| |
| if(!bSwap) |
| return; |
| } |
| } |
| |
| /*!*************************************************************************** |
| @brief Removes an element from the array. |
| @param[in] uiIndex The index to remove |
| @return success or failure |
| *****************************************************************************/ |
| virtual EPVRTError Remove(unsigned int uiIndex) |
| { |
| _ASSERT(uiIndex < m_uiSize); |
| if(m_uiSize == 0) |
| return PVR_FAIL; |
| |
| if(uiIndex == m_uiSize-1) |
| { |
| return RemoveLast(); |
| } |
| |
| m_uiSize--; |
| // Copy the data. memmove will only work for built-in types. |
| for(unsigned int uiNewIdx = uiIndex; uiNewIdx < m_uiSize; ++uiNewIdx) |
| { |
| m_pArray[uiNewIdx] = m_pArray[uiNewIdx+1]; |
| } |
| |
| return PVR_SUCCESS; |
| } |
| |
| /*!*************************************************************************** |
| @brief Removes the last element. Simply decrements the size value |
| @return success or failure |
| *****************************************************************************/ |
| virtual EPVRTError RemoveLast() |
| { |
| if(m_uiSize > 0) |
| { |
| m_uiSize--; |
| return PVR_SUCCESS; |
| } |
| else |
| { |
| return PVR_FAIL; |
| } |
| } |
| |
| protected: |
| unsigned int m_uiSize; /*!< Current size of contents of array */ |
| unsigned int m_uiCapacity; /*!< Currently allocated size of array */ |
| T *m_pArray; /*!< The actual array itself */ |
| }; |
| |
| // note "this" is required for ISO standard, C++ and gcc complains otherwise |
| // http://lists.apple.com/archives/Xcode-users//2005/Dec/msg00644.html |
| |
| /*!*************************************************************************** |
| @class CPVRTArrayManagedPointers |
| @brief Maintains an array of managed pointers. |
| *****************************************************************************/ |
| template<typename T> |
| class CPVRTArrayManagedPointers : public CPVRTArray<T*> |
| { |
| public: |
| /*!*************************************************************************** |
| @brief Destructor. |
| *****************************************************************************/ |
| virtual ~CPVRTArrayManagedPointers() |
| { |
| if(this->m_pArray) |
| { |
| for(unsigned int i=0;i<this->m_uiSize;i++) |
| { |
| delete(this->m_pArray[i]); |
| } |
| } |
| } |
| |
| /*!*************************************************************************** |
| @brief Removes an element from the array. |
| @param[in] uiIndex The index to remove. |
| @return success or failure |
| *****************************************************************************/ |
| virtual EPVRTError Remove(unsigned int uiIndex) |
| { |
| _ASSERT(uiIndex < this->m_uiSize); |
| if(this->m_uiSize == 0) |
| return PVR_FAIL; |
| |
| if(uiIndex == this->m_uiSize-1) |
| { |
| return this->RemoveLast(); |
| } |
| |
| unsigned int uiSize = (this->m_uiSize - (uiIndex+1)) * sizeof(T*); |
| |
| delete this->m_pArray[uiIndex]; |
| memmove(this->m_pArray + uiIndex, this->m_pArray + (uiIndex+1), uiSize); |
| |
| this->m_uiSize--; |
| return PVR_SUCCESS; |
| } |
| |
| /*!*************************************************************************** |
| @brief Removes the last element. Simply decrements the size value |
| @return success or failure |
| *****************************************************************************/ |
| virtual EPVRTError RemoveLast() |
| { |
| if(this->m_uiSize > 0 && this->m_pArray) |
| { |
| delete this->m_pArray[this->m_uiSize-1]; |
| this->m_uiSize--; |
| return PVR_SUCCESS; |
| } |
| else |
| { |
| return PVR_FAIL; |
| } |
| } |
| }; |
| |
| #endif // __PVRTARRAY_H__ |
| |
| /***************************************************************************** |
| End of file (PVRTArray.h) |
| *****************************************************************************/ |
| |