PVRTArray.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. /*!****************************************************************************
  2. @file PVRTArray.h
  3. @copyright Copyright (c) Imagination Technologies Limited.
  4. @brief Expanding array template class. Allows appending and direct
  5. access. Mixing access methods should be approached with caution.
  6. ******************************************************************************/
  7. #ifndef __PVRTARRAY_H__
  8. #define __PVRTARRAY_H__
  9. #include "PVRTGlobal.h"
  10. #include "PVRTError.h"
  11. /******************************************************************************
  12. ** Classes
  13. ******************************************************************************/
  14. /*!***************************************************************************
  15. @class CPVRTArray
  16. @brief Expanding array template class.
  17. *****************************************************************************/
  18. template<typename T>
  19. class CPVRTArray
  20. {
  21. public:
  22. /*!***************************************************************************
  23. @brief Blank constructor. Makes a default sized array.
  24. *****************************************************************************/
  25. CPVRTArray() : m_uiSize(0), m_uiCapacity(GetDefaultSize())
  26. {
  27. m_pArray = new T[m_uiCapacity];
  28. }
  29. /*!***************************************************************************
  30. @brief Constructor taking initial size of array in elements.
  31. @param[in] uiSize intial size of array
  32. *****************************************************************************/
  33. CPVRTArray(const unsigned int uiSize) : m_uiSize(0), m_uiCapacity(uiSize)
  34. {
  35. _ASSERT(uiSize != 0);
  36. m_pArray = new T[uiSize];
  37. }
  38. /*!***************************************************************************
  39. @brief Copy constructor.
  40. @param[in] original the other dynamic array
  41. *****************************************************************************/
  42. CPVRTArray(const CPVRTArray& original) : m_uiSize(original.m_uiSize),
  43. m_uiCapacity(original.m_uiCapacity)
  44. {
  45. m_pArray = new T[m_uiCapacity];
  46. for(unsigned int i=0;i<m_uiSize;i++)
  47. {
  48. m_pArray[i]=original.m_pArray[i];
  49. }
  50. }
  51. /*!***************************************************************************
  52. @brief constructor from ordinary array.
  53. @param[in] pArray an ordinary array
  54. @param[in] uiSize number of elements passed
  55. *****************************************************************************/
  56. CPVRTArray(const T* const pArray, const unsigned int uiSize) : m_uiSize(uiSize),
  57. m_uiCapacity(uiSize)
  58. {
  59. _ASSERT(uiSize != 0);
  60. m_pArray = new T[uiSize];
  61. for(unsigned int i=0;i<m_uiSize;i++)
  62. {
  63. m_pArray[i]=pArray[i];
  64. }
  65. }
  66. /*!***************************************************************************
  67. @brief constructor from a capacity and initial value.
  68. @param[in] uiSize initial capacity
  69. @param[in] val value to populate with
  70. *****************************************************************************/
  71. CPVRTArray(const unsigned int uiSize, const T& val) : m_uiSize(uiSize),
  72. m_uiCapacity(uiSize)
  73. {
  74. _ASSERT(uiSize != 0);
  75. m_pArray = new T[uiSize];
  76. for(unsigned int uiIndex = 0; uiIndex < m_uiSize; ++uiIndex)
  77. {
  78. m_pArray[uiIndex] = val;
  79. }
  80. }
  81. /*!***************************************************************************
  82. @brief Destructor.
  83. *****************************************************************************/
  84. virtual ~CPVRTArray()
  85. {
  86. if(m_pArray)
  87. delete [] m_pArray;
  88. }
  89. /*!***************************************************************************
  90. @brief Inserts an element into the array, expanding it
  91. if necessary.
  92. @param[in] pos The position to insert the new element at
  93. @param[in] addT The element to insert
  94. @return The index of the new item or -1 on failure.
  95. *****************************************************************************/
  96. int Insert(const unsigned int pos, const T& addT)
  97. {
  98. unsigned int uiIndex = pos;
  99. if(pos >= m_uiSize) // Are we adding to the end
  100. uiIndex = Append(addT);
  101. else
  102. {
  103. unsigned int uiNewCapacity = 0;
  104. T* pArray = m_pArray;
  105. if(m_uiSize >= m_uiCapacity)
  106. {
  107. uiNewCapacity = m_uiCapacity + 10; // Expand the array by 10.
  108. pArray = new T[uiNewCapacity]; // New Array
  109. if(!pArray)
  110. return -1; // Failed to allocate memory!
  111. // Copy the first half to the new array
  112. for(unsigned int i = 0; i < pos; ++i)
  113. {
  114. pArray[i] = m_pArray[i];
  115. }
  116. }
  117. // Copy last half to the new array
  118. for(unsigned int i = m_uiSize; i > pos; --i)
  119. {
  120. pArray[i] = m_pArray[i - 1];
  121. }
  122. // Insert our new element
  123. pArray[pos] = addT;
  124. uiIndex = pos;
  125. // Increase our size
  126. ++m_uiSize;
  127. // Switch pointers and free memory if needed
  128. if(pArray != m_pArray)
  129. {
  130. m_uiCapacity = uiNewCapacity;
  131. delete[] m_pArray;
  132. m_pArray = pArray;
  133. }
  134. }
  135. return uiIndex;
  136. }
  137. /*!***************************************************************************
  138. @brief Appends an element to the end of the array, expanding it
  139. if necessary.
  140. @param[in] addT The element to append
  141. @return The index of the new item.
  142. *****************************************************************************/
  143. unsigned int Append(const T& addT)
  144. {
  145. unsigned int uiIndex = Append();
  146. m_pArray[uiIndex] = addT;
  147. return uiIndex;
  148. }
  149. /*!***************************************************************************
  150. @brief Creates space for a new item, but doesn't add. Instead
  151. returns the index of the new item.
  152. @return The index of the new item.
  153. *****************************************************************************/
  154. unsigned int Append()
  155. {
  156. unsigned int uiIndex = m_uiSize;
  157. SetCapacity(m_uiSize+1);
  158. m_uiSize++;
  159. return uiIndex;
  160. }
  161. /*!***************************************************************************
  162. @brief Clears the array.
  163. *****************************************************************************/
  164. void Clear()
  165. {
  166. m_uiSize = 0U;
  167. }
  168. /*!***************************************************************************
  169. @brief Changes the array to the new size
  170. @param[in] uiSize New size of array
  171. *****************************************************************************/
  172. EPVRTError Resize(const unsigned int uiSize)
  173. {
  174. EPVRTError err = SetCapacity(uiSize);
  175. if(err != PVR_SUCCESS)
  176. return err;
  177. m_uiSize = uiSize;
  178. return PVR_SUCCESS;
  179. }
  180. /*!***************************************************************************
  181. @brief Expands array to new capacity
  182. @param[in] uiSize New capacity of array
  183. *****************************************************************************/
  184. EPVRTError SetCapacity(const unsigned int uiSize)
  185. {
  186. if(uiSize <= m_uiCapacity)
  187. return PVR_SUCCESS; // nothing to be done
  188. unsigned int uiNewCapacity;
  189. if(uiSize < m_uiCapacity*2)
  190. {
  191. uiNewCapacity = m_uiCapacity*2; // Ignore the new size. Expand to twice the previous size.
  192. }
  193. else
  194. {
  195. uiNewCapacity = uiSize;
  196. }
  197. T* pNewArray = new T[uiNewCapacity]; // New Array
  198. if(!pNewArray)
  199. return PVR_FAIL; // Failed to allocate memory!
  200. // Copy source data to new array
  201. for(unsigned int i = 0; i < m_uiSize; ++i)
  202. {
  203. pNewArray[i] = m_pArray[i];
  204. }
  205. // Switch pointers and free memory
  206. m_uiCapacity = uiNewCapacity;
  207. T* pOldArray = m_pArray;
  208. m_pArray = pNewArray;
  209. delete [] pOldArray;
  210. return PVR_SUCCESS;
  211. }
  212. /*!***************************************************************************
  213. @fn Copy
  214. @brief A copy function. Will attempt to copy from other CPVRTArrays
  215. if this is possible.
  216. @param[in] other The CPVRTArray needing copied
  217. *****************************************************************************/
  218. template<typename T2>
  219. void Copy(const CPVRTArray<T2>& other)
  220. {
  221. T* pNewArray = new T[other.GetCapacity()];
  222. if(pNewArray)
  223. {
  224. // Copy data
  225. for(unsigned int i = 0; i < other.GetSize(); i++)
  226. {
  227. pNewArray[i] = other[i];
  228. }
  229. // Free current array
  230. if(m_pArray)
  231. delete [] m_pArray;
  232. // Swap pointers
  233. m_pArray = pNewArray;
  234. m_uiCapacity = other.GetCapacity();
  235. m_uiSize = other.GetSize();
  236. }
  237. }
  238. /*!***************************************************************************
  239. @brief assignment operator.
  240. @param[in] other The CPVRTArray needing copied
  241. *****************************************************************************/
  242. CPVRTArray& operator=(const CPVRTArray<T>& other)
  243. {
  244. if(&other != this)
  245. Copy(other);
  246. return *this;
  247. }
  248. /*!***************************************************************************
  249. @brief appends an existing CPVRTArray on to this one.
  250. @param[in] other the array to append.
  251. *****************************************************************************/
  252. CPVRTArray& operator+=(const CPVRTArray<T>& other)
  253. {
  254. if(&other != this)
  255. {
  256. for(unsigned int uiIndex = 0; uiIndex < other.GetSize(); ++uiIndex)
  257. {
  258. Append(other[uiIndex]);
  259. }
  260. }
  261. return *this;
  262. }
  263. /*!***************************************************************************
  264. @brief Indexed access into array. Note that this has no error
  265. checking whatsoever
  266. @param[in] uiIndex index of element in array
  267. @return the element indexed
  268. *****************************************************************************/
  269. T& operator[](const unsigned int uiIndex)
  270. {
  271. _ASSERT(uiIndex < m_uiSize);
  272. return m_pArray[uiIndex];
  273. }
  274. /*!***************************************************************************
  275. @brief Indexed access into array. Note that this has no error checking whatsoever
  276. @param[in] uiIndex index of element in array
  277. @return The element indexed
  278. *****************************************************************************/
  279. const T& operator[](const unsigned int uiIndex) const
  280. {
  281. _ASSERT(uiIndex < m_uiSize);
  282. return m_pArray[uiIndex];
  283. }
  284. /*!***************************************************************************
  285. @return Size of array
  286. @brief Gives current size of array/number of elements
  287. *****************************************************************************/
  288. unsigned int GetSize() const
  289. {
  290. return m_uiSize;
  291. }
  292. /*!***************************************************************************
  293. @brief Gives the default size of array/number of elements
  294. @return Default size of array
  295. *****************************************************************************/
  296. static unsigned int GetDefaultSize()
  297. {
  298. return 16U;
  299. }
  300. /*!***************************************************************************
  301. @brief Gives current allocated size of array/number of elements
  302. @return Capacity of array
  303. *****************************************************************************/
  304. unsigned int GetCapacity() const
  305. {
  306. return m_uiCapacity;
  307. }
  308. /*!***************************************************************************
  309. @brief Indicates whether the given object resides inside the array.
  310. @param[in] object The object to check in the array
  311. @return true if object is contained in this array.
  312. *****************************************************************************/
  313. bool Contains(const T& object) const
  314. {
  315. for(unsigned int uiIndex = 0; uiIndex < m_uiSize; ++uiIndex)
  316. {
  317. if(m_pArray[uiIndex] == object)
  318. return true;
  319. }
  320. return false;
  321. }
  322. /*!***************************************************************************
  323. @brief Attempts to find the object in the array and returns a
  324. pointer if it is found, or NULL if not found. The time
  325. taken is O(N).
  326. @param[in] object The object to check in the array
  327. @return Pointer to the found object or NULL.
  328. *****************************************************************************/
  329. T* Find(const T& object) const
  330. {
  331. for(unsigned int uiIndex = 0; uiIndex < m_uiSize; ++uiIndex)
  332. {
  333. if(m_pArray[uiIndex] == object)
  334. return &m_pArray[uiIndex];
  335. }
  336. return NULL;
  337. }
  338. /*!***************************************************************************
  339. @brief Performs a merge-sort on the array. Pred should be an object that
  340. defines a bool operator().
  341. @param[in] predicate The object which defines "bool operator()"
  342. *****************************************************************************/
  343. template<class Pred>
  344. void Sort(Pred predicate)
  345. {
  346. _Sort(0, m_uiSize, predicate);
  347. }
  348. /*!***************************************************************************
  349. @brief Removes an element from the array.
  350. @param[in] uiIndex The index to remove
  351. @return success or failure
  352. *****************************************************************************/
  353. virtual EPVRTError Remove(unsigned int uiIndex)
  354. {
  355. _ASSERT(uiIndex < m_uiSize);
  356. if(m_uiSize == 0)
  357. return PVR_FAIL;
  358. if(uiIndex == m_uiSize-1)
  359. {
  360. return RemoveLast();
  361. }
  362. m_uiSize--;
  363. // Copy the data. memmove will only work for built-in types.
  364. for(unsigned int uiNewIdx = uiIndex; uiNewIdx < m_uiSize; ++uiNewIdx)
  365. {
  366. m_pArray[uiNewIdx] = m_pArray[uiNewIdx+1];
  367. }
  368. return PVR_SUCCESS;
  369. }
  370. /*!***************************************************************************
  371. @brief Removes the last element. Simply decrements the size value
  372. @return success or failure
  373. *****************************************************************************/
  374. virtual EPVRTError RemoveLast()
  375. {
  376. if(m_uiSize > 0)
  377. {
  378. m_uiSize--;
  379. return PVR_SUCCESS;
  380. }
  381. else
  382. {
  383. return PVR_FAIL;
  384. }
  385. }
  386. protected:
  387. enum eBounds
  388. {
  389. eLowerBounds,
  390. eUpperBounds,
  391. };
  392. /*!***************************************************************************
  393. @brief Internal sort algorithm
  394. @param[in] first The beginning index of the array
  395. @param[in] last The last index of the array
  396. @param[in] predicate A functor object to perform the comparison
  397. *****************************************************************************/
  398. template<class Pred>
  399. void _Sort(unsigned int first, unsigned int last, Pred predicate)
  400. {
  401. unsigned int size = last - first;
  402. if(size < 2)
  403. return;
  404. unsigned int middle = first + size / 2;
  405. _Sort(first, middle, predicate);
  406. _Sort(middle, last, predicate);
  407. _SortMerge(first, middle, last, middle-first, last-middle, predicate);
  408. }
  409. /*!***************************************************************************
  410. @brief Internal sort algorithm - in-place merge method
  411. @param[in] first The beginning index of the array
  412. @param[in] middle The middle index of the array
  413. @param[in] last The last index of the array
  414. @param[in] len1 Length of first half of the array
  415. @param[in] len2 Length of the second half of the array
  416. @param[in] predicate A functor object to perform the comparison
  417. *****************************************************************************/
  418. template<class Pred>
  419. void _SortMerge(unsigned int first, unsigned int middle, unsigned int last, int len1, int len2, Pred predicate)
  420. {
  421. if(len1 == 0 || len2 == 0)
  422. return;
  423. if(len1 + len2 == 2)
  424. {
  425. if(predicate(m_pArray[middle], m_pArray[first]))
  426. PVRTswap(m_pArray[first], m_pArray[middle]);
  427. return;
  428. }
  429. unsigned int firstCut = first;
  430. unsigned int secondCut = middle;
  431. int dist1 = 0;
  432. int dist2 = 0;
  433. if(len1 > len2)
  434. {
  435. dist1 = len1 / 2;
  436. firstCut += dist1;
  437. secondCut = _SortBounds(middle, last, m_pArray[firstCut], eLowerBounds, predicate);
  438. dist2 += secondCut - middle;
  439. }
  440. else
  441. {
  442. dist2 = len2 / 2;
  443. secondCut += dist2;
  444. firstCut = _SortBounds(first, middle, m_pArray[secondCut], eUpperBounds, predicate);
  445. dist1 += firstCut - first;
  446. }
  447. unsigned int newMiddle = _SortRotate(firstCut, middle, secondCut);
  448. _SortMerge(first, firstCut, newMiddle, dist1, dist2, predicate);
  449. _SortMerge(newMiddle, secondCut, last, len1-dist1, len2-dist2, predicate);
  450. }
  451. /*!***************************************************************************
  452. @brief Internal sort algorithm - returns the bounded index of the range
  453. @param[in] first The beginning index of the array
  454. @param[in] last The last index of the array
  455. @param[in] v Comparison object
  456. @param[in] bounds Which bound to check (upper or lower)
  457. @param[in] predicate A functor object to perform the comparison
  458. *****************************************************************************/
  459. template<class Pred>
  460. unsigned int _SortBounds(unsigned int first, unsigned int last, const T& v, eBounds bounds, Pred predicate)
  461. {
  462. int count = last - first, step;
  463. unsigned int idx;
  464. while(count > 0)
  465. {
  466. step = count / 2;
  467. idx = first + step;
  468. if((bounds == eLowerBounds && predicate(m_pArray[idx], v)) || (bounds == eUpperBounds && !predicate(v, m_pArray[idx])))
  469. {
  470. first = ++idx;
  471. count -= step + 1;
  472. }
  473. else
  474. {
  475. count = step;
  476. }
  477. }
  478. return first;
  479. }
  480. /*!***************************************************************************
  481. @brief Internal sort algorithm - rotates the contents of the array such
  482. that the middle becomes the first element
  483. @param[in] first The beginning index of the array
  484. @param[in] middle The middle index of the array
  485. @param[in] last The last index of the array
  486. *****************************************************************************/
  487. int _SortRotate(unsigned int first, unsigned int middle, unsigned int last)
  488. {
  489. if(first == middle)
  490. return last;
  491. if(last == middle)
  492. return first;
  493. unsigned int newFirst = middle;
  494. do
  495. {
  496. PVRTswap(m_pArray[first++], m_pArray[newFirst++]);
  497. if(first == middle)
  498. middle = newFirst;
  499. } while (newFirst != last);
  500. unsigned int newMiddle = first;
  501. newFirst = middle;
  502. while(newFirst != last)
  503. {
  504. PVRTswap(m_pArray[first++], m_pArray[newFirst++]);
  505. if(first == middle)
  506. middle = newFirst;
  507. else if(newFirst == last)
  508. newFirst = middle;
  509. }
  510. return newMiddle;
  511. }
  512. protected:
  513. unsigned int m_uiSize; /*!< Current size of contents of array */
  514. unsigned int m_uiCapacity; /*!< Currently allocated size of array */
  515. T *m_pArray; /*!< The actual array itself */
  516. };
  517. // note "this" is required for ISO standard, C++ and gcc complains otherwise
  518. // http://lists.apple.com/archives/Xcode-users//2005/Dec/msg00644.html
  519. /*!***************************************************************************
  520. @class CPVRTArrayManagedPointers
  521. @brief Maintains an array of managed pointers.
  522. *****************************************************************************/
  523. template<typename T>
  524. class CPVRTArrayManagedPointers : public CPVRTArray<T*>
  525. {
  526. public:
  527. /*!***************************************************************************
  528. @brief Destructor.
  529. *****************************************************************************/
  530. virtual ~CPVRTArrayManagedPointers()
  531. {
  532. if(this->m_pArray)
  533. {
  534. for(unsigned int i=0;i<this->m_uiSize;i++)
  535. {
  536. delete(this->m_pArray[i]);
  537. }
  538. }
  539. }
  540. /*!***************************************************************************
  541. @brief Removes an element from the array.
  542. @param[in] uiIndex The index to remove.
  543. @return success or failure
  544. *****************************************************************************/
  545. virtual EPVRTError Remove(unsigned int uiIndex)
  546. {
  547. _ASSERT(uiIndex < this->m_uiSize);
  548. if(this->m_uiSize == 0)
  549. return PVR_FAIL;
  550. if(uiIndex == this->m_uiSize-1)
  551. {
  552. return this->RemoveLast();
  553. }
  554. unsigned int uiSize = (this->m_uiSize - (uiIndex+1)) * sizeof(T*);
  555. delete this->m_pArray[uiIndex];
  556. memmove(this->m_pArray + uiIndex, this->m_pArray + (uiIndex+1), uiSize);
  557. this->m_uiSize--;
  558. return PVR_SUCCESS;
  559. }
  560. /*!***************************************************************************
  561. @brief Removes the last element. Simply decrements the size value
  562. @return success or failure
  563. *****************************************************************************/
  564. virtual EPVRTError RemoveLast()
  565. {
  566. if(this->m_uiSize > 0 && this->m_pArray)
  567. {
  568. delete this->m_pArray[this->m_uiSize-1];
  569. this->m_uiSize--;
  570. return PVR_SUCCESS;
  571. }
  572. else
  573. {
  574. return PVR_FAIL;
  575. }
  576. }
  577. };
  578. #endif // __PVRTARRAY_H__
  579. /*****************************************************************************
  580. End of file (PVRTArray.h)
  581. *****************************************************************************/