StaticList.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #ifndef __STATICLIST_H__
  21. #define __STATICLIST_H__
  22. #include "List.h"
  23. /*
  24. ===============================================================================
  25. Static list template
  26. A non-growing, memset-able list using no memory allocation.
  27. ===============================================================================
  28. */
  29. template<class type,int size>
  30. class idStaticList {
  31. public:
  32. idStaticList();
  33. idStaticList( const idStaticList<type,size> &other );
  34. ~idStaticList<type,size>();
  35. void Clear(); // marks the list as empty. does not deallocate or intialize data.
  36. int Num() const; // returns number of elements in list
  37. int Max() const; // returns the maximum number of elements in the list
  38. void SetNum( int newnum ); // set number of elements in list
  39. // sets the number of elements in list and initializes any newly allocated elements to the given value
  40. void SetNum( int newNum, const type & initValue );
  41. size_t Allocated() const; // returns total size of allocated memory
  42. size_t Size() const; // returns total size of allocated memory including size of list type
  43. size_t MemoryUsed() const; // returns size of the used elements in the list
  44. const type & operator[]( int index ) const;
  45. type & operator[]( int index );
  46. type * Ptr(); // returns a pointer to the list
  47. const type * Ptr() const; // returns a pointer to the list
  48. type * Alloc(); // returns reference to a new data element at the end of the list. returns NULL when full.
  49. int Append( const type & obj ); // append element
  50. int Append( const idStaticList<type,size> &other ); // append list
  51. int AddUnique( const type & obj ); // add unique element
  52. int Insert( const type & obj, int index = 0 ); // insert the element at the given index
  53. int FindIndex( const type & obj ) const; // find the index for the given element
  54. type * Find( type const & obj ) const; // find pointer to the given element
  55. int FindNull() const; // find the index for the first NULL pointer in the list
  56. int IndexOf( const type *obj ) const; // returns the index for the pointer to an element in the list
  57. bool RemoveIndex( int index ); // remove the element at the given index
  58. bool RemoveIndexFast( int index ); // remove the element at the given index
  59. bool Remove( const type & obj ); // remove the element
  60. void Swap( idStaticList<type,size> &other ); // swap the contents of the lists
  61. void DeleteContents( bool clear ); // delete the contents of the list
  62. void Sort( const idSort<type> & sort = idSort_QuickDefault<type>() );
  63. private:
  64. int num;
  65. type list[ size ];
  66. private:
  67. // resizes list to the given number of elements
  68. void Resize( int newsize );
  69. };
  70. /*
  71. ================
  72. idStaticList<type,size>::idStaticList()
  73. ================
  74. */
  75. template<class type,int size>
  76. ID_INLINE idStaticList<type,size>::idStaticList() {
  77. num = 0;
  78. }
  79. /*
  80. ================
  81. idStaticList<type,size>::idStaticList( const idStaticList<type,size> &other )
  82. ================
  83. */
  84. template<class type,int size>
  85. ID_INLINE idStaticList<type,size>::idStaticList( const idStaticList<type,size> &other ) {
  86. *this = other;
  87. }
  88. /*
  89. ================
  90. idStaticList<type,size>::~idStaticList<type,size>
  91. ================
  92. */
  93. template<class type,int size>
  94. ID_INLINE idStaticList<type,size>::~idStaticList() {
  95. }
  96. /*
  97. ================
  98. idStaticList<type,size>::Clear
  99. Sets the number of elements in the list to 0. Assumes that type automatically handles freeing up memory.
  100. ================
  101. */
  102. template<class type,int size>
  103. ID_INLINE void idStaticList<type,size>::Clear() {
  104. num = 0;
  105. }
  106. /*
  107. ========================
  108. idList<_type_,_tag_>::Sort
  109. Performs a QuickSort on the list using the supplied sort algorithm.
  110. Note: The data is merely moved around the list, so any pointers to data within the list may
  111. no longer be valid.
  112. ========================
  113. */
  114. template< class type,int size >
  115. ID_INLINE void idStaticList<type,size>::Sort( const idSort<type> & sort ) {
  116. if ( list == NULL ) {
  117. return;
  118. }
  119. sort.Sort( Ptr(), Num() );
  120. }
  121. /*
  122. ================
  123. idStaticList<type,size>::DeleteContents
  124. Calls the destructor of all elements in the list. Conditionally frees up memory used by the list.
  125. Note that this only works on lists containing pointers to objects and will cause a compiler error
  126. if called with non-pointers. Since the list was not responsible for allocating the object, it has
  127. no information on whether the object still exists or not, so care must be taken to ensure that
  128. the pointers are still valid when this function is called. Function will set all pointers in the
  129. list to NULL.
  130. ================
  131. */
  132. template<class type,int size>
  133. ID_INLINE void idStaticList<type,size>::DeleteContents( bool clear ) {
  134. int i;
  135. for( i = 0; i < num; i++ ) {
  136. delete list[ i ];
  137. list[ i ] = NULL;
  138. }
  139. if ( clear ) {
  140. Clear();
  141. } else {
  142. memset( list, 0, sizeof( list ) );
  143. }
  144. }
  145. /*
  146. ================
  147. idStaticList<type,size>::Num
  148. Returns the number of elements currently contained in the list.
  149. ================
  150. */
  151. template<class type,int size>
  152. ID_INLINE int idStaticList<type,size>::Num() const {
  153. return num;
  154. }
  155. /*
  156. ================
  157. idStaticList<type,size>::Num
  158. Returns the maximum number of elements in the list.
  159. ================
  160. */
  161. template<class type,int size>
  162. ID_INLINE int idStaticList<type,size>::Max() const {
  163. return size;
  164. }
  165. /*
  166. ================
  167. idStaticList<type>::Allocated
  168. ================
  169. */
  170. template<class type,int size>
  171. ID_INLINE size_t idStaticList<type,size>::Allocated() const {
  172. return size * sizeof( type );
  173. }
  174. /*
  175. ================
  176. idStaticList<type>::Size
  177. ================
  178. */
  179. template<class type,int size>
  180. ID_INLINE size_t idStaticList<type,size>::Size() const {
  181. return sizeof( idStaticList<type,size> ) + Allocated();
  182. }
  183. /*
  184. ================
  185. idStaticList<type,size>::Num
  186. ================
  187. */
  188. template<class type,int size>
  189. ID_INLINE size_t idStaticList<type,size>::MemoryUsed() const {
  190. return num * sizeof( list[ 0 ] );
  191. }
  192. /*
  193. ================
  194. idStaticList<type,size>::SetNum
  195. Set number of elements in list.
  196. ================
  197. */
  198. template<class type,int size>
  199. ID_INLINE void idStaticList<type,size>::SetNum( int newnum ) {
  200. assert( newnum >= 0 );
  201. assert( newnum <= size );
  202. num = newnum;
  203. }
  204. /*
  205. ========================
  206. idStaticList<_type_,_tag_>::SetNum
  207. ========================
  208. */
  209. template< class type,int size >
  210. ID_INLINE void idStaticList<type,size>::SetNum( int newNum, const type &initValue ) {
  211. assert( newNum >= 0 );
  212. newNum = Min( newNum, size );
  213. assert( newNum <= size );
  214. for ( int i = num; i < newNum; i++ ) {
  215. list[i] = initValue;
  216. }
  217. num = newNum;
  218. }
  219. /*
  220. ================
  221. idStaticList<type,size>::operator[] const
  222. Access operator. Index must be within range or an assert will be issued in debug builds.
  223. Release builds do no range checking.
  224. ================
  225. */
  226. template<class type,int size>
  227. ID_INLINE const type &idStaticList<type,size>::operator[]( int index ) const {
  228. assert( index >= 0 );
  229. assert( index < num );
  230. return list[ index ];
  231. }
  232. /*
  233. ================
  234. idStaticList<type,size>::operator[]
  235. Access operator. Index must be within range or an assert will be issued in debug builds.
  236. Release builds do no range checking.
  237. ================
  238. */
  239. template<class type,int size>
  240. ID_INLINE type &idStaticList<type,size>::operator[]( int index ) {
  241. assert( index >= 0 );
  242. assert( index < num );
  243. return list[ index ];
  244. }
  245. /*
  246. ================
  247. idStaticList<type,size>::Ptr
  248. Returns a pointer to the begining of the array. Useful for iterating through the list in loops.
  249. Note: may return NULL if the list is empty.
  250. FIXME: Create an iterator template for this kind of thing.
  251. ================
  252. */
  253. template<class type,int size>
  254. ID_INLINE type *idStaticList<type,size>::Ptr() {
  255. return &list[ 0 ];
  256. }
  257. /*
  258. ================
  259. idStaticList<type,size>::Ptr
  260. Returns a pointer to the begining of the array. Useful for iterating through the list in loops.
  261. Note: may return NULL if the list is empty.
  262. FIXME: Create an iterator template for this kind of thing.
  263. ================
  264. */
  265. template<class type,int size>
  266. ID_INLINE const type *idStaticList<type,size>::Ptr() const {
  267. return &list[ 0 ];
  268. }
  269. /*
  270. ================
  271. idStaticList<type,size>::Alloc
  272. Returns a pointer to a new data element at the end of the list.
  273. ================
  274. */
  275. template<class type,int size>
  276. ID_INLINE type *idStaticList<type,size>::Alloc() {
  277. if ( num >= size ) {
  278. return NULL;
  279. }
  280. return &list[ num++ ];
  281. }
  282. /*
  283. ================
  284. idStaticList<type,size>::Append
  285. Increases the size of the list by one element and copies the supplied data into it.
  286. Returns the index of the new element, or -1 when list is full.
  287. ================
  288. */
  289. template<class type,int size>
  290. ID_INLINE int idStaticList<type,size>::Append( type const & obj ) {
  291. assert( num < size );
  292. if ( num < size ) {
  293. list[ num ] = obj;
  294. num++;
  295. return num - 1;
  296. }
  297. return -1;
  298. }
  299. /*
  300. ================
  301. idStaticList<type,size>::Insert
  302. Increases the size of the list by at leat one element if necessary
  303. and inserts the supplied data into it.
  304. Returns the index of the new element, or -1 when list is full.
  305. ================
  306. */
  307. template<class type,int size>
  308. ID_INLINE int idStaticList<type,size>::Insert( type const & obj, int index ) {
  309. int i;
  310. assert( num < size );
  311. if ( num >= size ) {
  312. return -1;
  313. }
  314. assert( index >= 0 );
  315. if ( index < 0 ) {
  316. index = 0;
  317. } else if ( index > num ) {
  318. index = num;
  319. }
  320. for( i = num; i > index; --i ) {
  321. list[i] = list[i-1];
  322. }
  323. num++;
  324. list[index] = obj;
  325. return index;
  326. }
  327. /*
  328. ================
  329. idStaticList<type,size>::Append
  330. adds the other list to this one
  331. Returns the size of the new combined list
  332. ================
  333. */
  334. template<class type,int size>
  335. ID_INLINE int idStaticList<type,size>::Append( const idStaticList<type,size> &other ) {
  336. int i;
  337. int n = other.Num();
  338. if ( num + n > size ) {
  339. n = size - num;
  340. }
  341. for( i = 0; i < n; i++ ) {
  342. list[i + num] = other.list[i];
  343. }
  344. num += n;
  345. return Num();
  346. }
  347. /*
  348. ================
  349. idStaticList<type,size>::AddUnique
  350. Adds the data to the list if it doesn't already exist. Returns the index of the data in the list.
  351. ================
  352. */
  353. template<class type,int size>
  354. ID_INLINE int idStaticList<type,size>::AddUnique( type const & obj ) {
  355. int index;
  356. index = FindIndex( obj );
  357. if ( index < 0 ) {
  358. index = Append( obj );
  359. }
  360. return index;
  361. }
  362. /*
  363. ================
  364. idStaticList<type,size>::FindIndex
  365. Searches for the specified data in the list and returns it's index. Returns -1 if the data is not found.
  366. ================
  367. */
  368. template<class type,int size>
  369. ID_INLINE int idStaticList<type,size>::FindIndex( type const & obj ) const {
  370. int i;
  371. for( i = 0; i < num; i++ ) {
  372. if ( list[ i ] == obj ) {
  373. return i;
  374. }
  375. }
  376. // Not found
  377. return -1;
  378. }
  379. /*
  380. ================
  381. idStaticList<type,size>::Find
  382. Searches for the specified data in the list and returns it's address. Returns NULL if the data is not found.
  383. ================
  384. */
  385. template<class type,int size>
  386. ID_INLINE type *idStaticList<type,size>::Find( type const & obj ) const {
  387. int i;
  388. i = FindIndex( obj );
  389. if ( i >= 0 ) {
  390. return (type *) &list[ i ];
  391. }
  392. return NULL;
  393. }
  394. /*
  395. ================
  396. idStaticList<type,size>::FindNull
  397. Searches for a NULL pointer in the list. Returns -1 if NULL is not found.
  398. NOTE: This function can only be called on lists containing pointers. Calling it
  399. on non-pointer lists will cause a compiler error.
  400. ================
  401. */
  402. template<class type,int size>
  403. ID_INLINE int idStaticList<type,size>::FindNull() const {
  404. int i;
  405. for( i = 0; i < num; i++ ) {
  406. if ( list[ i ] == NULL ) {
  407. return i;
  408. }
  409. }
  410. // Not found
  411. return -1;
  412. }
  413. /*
  414. ================
  415. idStaticList<type,size>::IndexOf
  416. Takes a pointer to an element in the list and returns the index of the element.
  417. This is NOT a guarantee that the object is really in the list.
  418. Function will assert in debug builds if pointer is outside the bounds of the list,
  419. but remains silent in release builds.
  420. ================
  421. */
  422. template<class type,int size>
  423. ID_INLINE int idStaticList<type,size>::IndexOf( type const *objptr ) const {
  424. int index;
  425. index = objptr - list;
  426. assert( index >= 0 );
  427. assert( index < num );
  428. return index;
  429. }
  430. /*
  431. ================
  432. idStaticList<type,size>::RemoveIndex
  433. Removes the element at the specified index and moves all data following the element down to fill in the gap.
  434. The number of elements in the list is reduced by one. Returns false if the index is outside the bounds of the list.
  435. Note that the element is not destroyed, so any memory used by it may not be freed until the destruction of the list.
  436. ================
  437. */
  438. template<class type,int size>
  439. ID_INLINE bool idStaticList<type,size>::RemoveIndex( int index ) {
  440. int i;
  441. assert( index >= 0 );
  442. assert( index < num );
  443. if ( ( index < 0 ) || ( index >= num ) ) {
  444. return false;
  445. }
  446. num--;
  447. for( i = index; i < num; i++ ) {
  448. list[ i ] = list[ i + 1 ];
  449. }
  450. return true;
  451. }
  452. /*
  453. ========================
  454. idList<_type_,_tag_>::RemoveIndexFast
  455. Removes the element at the specified index and moves the last element into its spot, rather
  456. than moving the whole array down by one. Of course, this doesn't maintain the order of
  457. elements! The number of elements in the list is reduced by one.
  458. return: bool - false if the data is not found in the list.
  459. NOTE: The element is not destroyed, so any memory used by it may not be freed until the
  460. destruction of the list.
  461. ========================
  462. */
  463. template< typename _type_,int size >
  464. ID_INLINE bool idStaticList<_type_,size>::RemoveIndexFast( int index ) {
  465. if ( ( index < 0 ) || ( index >= num ) ) {
  466. return false;
  467. }
  468. num--;
  469. if ( index != num ) {
  470. list[ index ] = list[ num ];
  471. }
  472. return true;
  473. }
  474. /*
  475. ================
  476. idStaticList<type,size>::Remove
  477. Removes the element if it is found within the list and moves all data following the element down to fill in the gap.
  478. The number of elements in the list is reduced by one. Returns false if the data is not found in the list. Note that
  479. the element is not destroyed, so any memory used by it may not be freed until the destruction of the list.
  480. ================
  481. */
  482. template<class type,int size>
  483. ID_INLINE bool idStaticList<type,size>::Remove( type const & obj ) {
  484. int index;
  485. index = FindIndex( obj );
  486. if ( index >= 0 ) {
  487. return RemoveIndex( index );
  488. }
  489. return false;
  490. }
  491. /*
  492. ================
  493. idStaticList<type,size>::Swap
  494. Swaps the contents of two lists
  495. ================
  496. */
  497. template<class type,int size>
  498. ID_INLINE void idStaticList<type,size>::Swap( idStaticList<type,size> &other ) {
  499. idStaticList<type,size> temp = *this;
  500. *this = other;
  501. other = temp;
  502. }
  503. // debug tool to find uses of idlist that are dynamically growing
  504. // Ideally, most lists on shipping titles will explicitly set their size correctly
  505. // instead of relying on allocate-on-add
  506. void BreakOnListGrowth();
  507. void BreakOnListDefault();
  508. /*
  509. ========================
  510. idList<_type_,_tag_>::Resize
  511. Allocates memory for the amount of elements requested while keeping the contents intact.
  512. Contents are copied using their = operator so that data is correctly instantiated.
  513. ========================
  514. */
  515. template< class type,int size >
  516. ID_INLINE void idStaticList<type,size>::Resize( int newsize ) {
  517. assert( newsize >= 0 );
  518. // free up the list if no data is being reserved
  519. if ( newsize <= 0 ) {
  520. Clear();
  521. return;
  522. }
  523. if ( newsize == size ) {
  524. // not changing the size, so just exit
  525. return;
  526. }
  527. assert( newsize < size );
  528. return;
  529. }
  530. #endif /* !__STATICLIST_H__ */