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