|  | /*!**************************************************************************** | 
|  |  | 
|  | @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) | 
|  | *****************************************************************************/ | 
|  |  |