List.h 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038
  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 __LIST_H__
  21. #define __LIST_H__
  22. #include <new>
  23. /*
  24. ===============================================================================
  25. List template
  26. Does not allocate memory until the first item is added.
  27. ===============================================================================
  28. */
  29. /*
  30. ========================
  31. idListArrayNew
  32. ========================
  33. */
  34. template< typename _type_, memTag_t _tag_ >
  35. ID_INLINE void * idListArrayNew( int num, bool zeroBuffer ) {
  36. _type_ * ptr = NULL;
  37. if ( zeroBuffer ) {
  38. ptr = (_type_ *)Mem_ClearedAlloc( sizeof(_type_) * num, _tag_ );
  39. } else {
  40. ptr = (_type_ *)Mem_Alloc( sizeof(_type_) * num, _tag_ );
  41. }
  42. for ( int i = 0; i < num; i++ ) {
  43. new ( &ptr[i] ) _type_;
  44. }
  45. return ptr;
  46. }
  47. /*
  48. ========================
  49. idListArrayDelete
  50. ========================
  51. */
  52. template< typename _type_ >
  53. ID_INLINE void idListArrayDelete( void *ptr, int num ) {
  54. // Call the destructors on all the elements
  55. for ( int i = 0; i < num; i++ ) {
  56. ((_type_ *)ptr)[i].~_type_();
  57. }
  58. Mem_Free( ptr );
  59. }
  60. /*
  61. ========================
  62. idListArrayResize
  63. ========================
  64. */
  65. template< typename _type_, memTag_t _tag_ >
  66. ID_INLINE void * idListArrayResize( void * voldptr, int oldNum, int newNum, bool zeroBuffer ) {
  67. _type_ * oldptr = (_type_ *)voldptr;
  68. _type_ * newptr = NULL;
  69. if ( newNum > 0 ) {
  70. newptr = (_type_ *)idListArrayNew<_type_, _tag_>( newNum, zeroBuffer );
  71. int overlap = Min( oldNum, newNum );
  72. for ( int i = 0; i < overlap; i++ ) {
  73. newptr[i] = oldptr[i];
  74. }
  75. }
  76. idListArrayDelete<_type_>( voldptr, oldNum );
  77. return newptr;
  78. }
  79. /*
  80. ================
  81. idListNewElement<type>
  82. ================
  83. */
  84. template< class type >
  85. ID_INLINE type *idListNewElement( void ) {
  86. return new type;
  87. }
  88. template< typename _type_, memTag_t _tag_ = TAG_IDLIB_LIST >
  89. class idList {
  90. public:
  91. typedef int cmp_t( const _type_ *, const _type_ * );
  92. typedef _type_ new_t();
  93. idList( int newgranularity = 16 );
  94. idList( const idList &other );
  95. ~idList();
  96. void Clear(); // clear the list
  97. int Num() const; // returns number of elements in list
  98. int NumAllocated() const; // returns number of elements allocated for
  99. void SetGranularity( int newgranularity ); // set new granularity
  100. int GetGranularity() const; // get the current granularity
  101. size_t Allocated() const; // returns total size of allocated memory
  102. size_t Size() const; // returns total size of allocated memory including size of list _type_
  103. size_t MemoryUsed() const; // returns size of the used elements in the list
  104. idList<_type_,_tag_> & operator=( const idList<_type_,_tag_> &other );
  105. const _type_ & operator[]( int index ) const;
  106. _type_ & operator[]( int index );
  107. void Condense(); // resizes list to exactly the number of elements it contains
  108. void Resize( int newsize ); // resizes list to the given number of elements
  109. void Resize( int newsize, int newgranularity ); // resizes list and sets new granularity
  110. void SetNum( int newnum ); // set number of elements in list and resize to exactly this number if needed
  111. void AssureSize( int newSize); // assure list has given number of elements, but leave them uninitialized
  112. void AssureSize( int newSize, const _type_ &initValue ); // assure list has given number of elements and initialize any new elements
  113. void AssureSizeAlloc( int newSize, new_t *allocator ); // assure the pointer list has the given number of elements and allocate any new elements
  114. _type_ * Ptr(); // returns a pointer to the list
  115. const _type_ * Ptr() const; // returns a pointer to the list
  116. _type_ & Alloc(); // returns reference to a new data element at the end of the list
  117. int Append( const _type_ & obj ); // append element
  118. int Append( const idList &other ); // append list
  119. int AddUnique( const _type_ & obj ); // add unique element
  120. int Insert( const _type_ & obj, int index = 0 ); // insert the element at the given index
  121. int FindIndex( const _type_ & obj ) const; // find the index for the given element
  122. _type_ * Find( _type_ const & obj ) const; // find pointer to the given element
  123. int FindNull() const; // find the index for the first NULL pointer in the list
  124. int IndexOf( const _type_ *obj ) const; // returns the index for the pointer to an element in the list
  125. bool RemoveIndex( int index ); // remove the element at the given index
  126. // removes the element at the given index and places the last element into its spot - DOES NOT PRESERVE LIST ORDER
  127. bool RemoveIndexFast( int index );
  128. bool Remove( const _type_ & obj ); // remove the element
  129. // void Sort( cmp_t *compare = ( cmp_t * )&idListSortCompare<_type_, _tag_> );
  130. void SortWithTemplate( const idSort<_type_> & sort = idSort_QuickDefault<_type_>() );
  131. // void SortSubSection( int startIndex, int endIndex, cmp_t *compare = ( cmp_t * )&idListSortCompare<_type_> );
  132. void Swap( idList &other ); // swap the contents of the lists
  133. void DeleteContents( bool clear = true ); // delete the contents of the list
  134. //------------------------
  135. // auto-cast to other idList types with a different memory tag
  136. //------------------------
  137. template< memTag_t _t_ >
  138. operator idList<_type_, _t_> & () {
  139. return *reinterpret_cast<idList<_type_, _t_> *>( this );
  140. }
  141. template< memTag_t _t_>
  142. operator const idList<_type_, _t_> & () const {
  143. return *reinterpret_cast<const idList<_type_, _t_> *>( this );
  144. }
  145. //------------------------
  146. // memTag
  147. //
  148. // Changing the memTag when the list has an allocated buffer will
  149. // result in corruption of the memory statistics.
  150. //------------------------
  151. memTag_t GetMemTag() const { return (memTag_t)memTag; };
  152. void SetMemTag( memTag_t tag_ ) { memTag = (byte)tag_; };
  153. private:
  154. int num;
  155. int size;
  156. int granularity;
  157. _type_ * list;
  158. byte memTag;
  159. };
  160. /*
  161. ================
  162. idList<_type_,_tag_>::idList( int )
  163. ================
  164. */
  165. template< typename _type_, memTag_t _tag_ >
  166. ID_INLINE idList<_type_,_tag_>::idList( int newgranularity ) {
  167. assert( newgranularity > 0 );
  168. list = NULL;
  169. granularity = newgranularity;
  170. memTag = _tag_;
  171. Clear();
  172. }
  173. /*
  174. ================
  175. idList<_type_,_tag_>::idList( const idList< _type_, _tag_ > &other )
  176. ================
  177. */
  178. template< typename _type_, memTag_t _tag_ >
  179. ID_INLINE idList<_type_,_tag_>::idList( const idList &other ) {
  180. list = NULL;
  181. *this = other;
  182. }
  183. /*
  184. ================
  185. idList<_type_,_tag_>::~idList< _type_, _tag_ >
  186. ================
  187. */
  188. template< typename _type_, memTag_t _tag_ >
  189. ID_INLINE idList<_type_,_tag_>::~idList() {
  190. Clear();
  191. }
  192. /*
  193. ================
  194. idList<_type_,_tag_>::Clear
  195. Frees up the memory allocated by the list. Assumes that _type_ automatically handles freeing up memory.
  196. ================
  197. */
  198. template< typename _type_, memTag_t _tag_ >
  199. ID_INLINE void idList<_type_,_tag_>::Clear() {
  200. if ( list ) {
  201. idListArrayDelete< _type_ >( list, size );
  202. }
  203. list = NULL;
  204. num = 0;
  205. size = 0;
  206. }
  207. /*
  208. ================
  209. idList<_type_,_tag_>::DeleteContents
  210. Calls the destructor of all elements in the list. Conditionally frees up memory used by the list.
  211. Note that this only works on lists containing pointers to objects and will cause a compiler error
  212. if called with non-pointers. Since the list was not responsible for allocating the object, it has
  213. no information on whether the object still exists or not, so care must be taken to ensure that
  214. the pointers are still valid when this function is called. Function will set all pointers in the
  215. list to NULL.
  216. ================
  217. */
  218. template< typename _type_, memTag_t _tag_ >
  219. ID_INLINE void idList<_type_,_tag_>::DeleteContents( bool clear ) {
  220. int i;
  221. for( i = 0; i < num; i++ ) {
  222. delete list[ i ];
  223. list[ i ] = NULL;
  224. }
  225. if ( clear ) {
  226. Clear();
  227. } else {
  228. memset( list, 0, size * sizeof( _type_ ) );
  229. }
  230. }
  231. /*
  232. ================
  233. idList<_type_,_tag_>::Allocated
  234. return total memory allocated for the list in bytes, but doesn't take into account additional memory allocated by _type_
  235. ================
  236. */
  237. template< typename _type_, memTag_t _tag_ >
  238. ID_INLINE size_t idList<_type_,_tag_>::Allocated() const {
  239. return size * sizeof( _type_ );
  240. }
  241. /*
  242. ================
  243. idList<_type_,_tag_>::Size
  244. return total size of list in bytes, but doesn't take into account additional memory allocated by _type_
  245. ================
  246. */
  247. template< typename _type_, memTag_t _tag_ >
  248. ID_INLINE size_t idList<_type_,_tag_>::Size() const {
  249. return sizeof( idList< _type_, _tag_ > ) + Allocated();
  250. }
  251. /*
  252. ================
  253. idList<_type_,_tag_>::MemoryUsed
  254. ================
  255. */
  256. template< typename _type_, memTag_t _tag_ >
  257. ID_INLINE size_t idList<_type_,_tag_>::MemoryUsed() const {
  258. return num * sizeof( *list );
  259. }
  260. /*
  261. ================
  262. idList<_type_,_tag_>::Num
  263. Returns the number of elements currently contained in the list.
  264. Note that this is NOT an indication of the memory allocated.
  265. ================
  266. */
  267. template< typename _type_, memTag_t _tag_ >
  268. ID_INLINE int idList<_type_,_tag_>::Num() const {
  269. return num;
  270. }
  271. /*
  272. ================
  273. idList<_type_,_tag_>::NumAllocated
  274. Returns the number of elements currently allocated for.
  275. ================
  276. */
  277. template< typename _type_, memTag_t _tag_ >
  278. ID_INLINE int idList<_type_,_tag_>::NumAllocated() const {
  279. return size;
  280. }
  281. /*
  282. ================
  283. idList<_type_,_tag_>::SetNum
  284. ================
  285. */
  286. template< typename _type_, memTag_t _tag_ >
  287. ID_INLINE void idList<_type_,_tag_>::SetNum( int newnum ) {
  288. assert( newnum >= 0 );
  289. if ( newnum > size ) {
  290. Resize( newnum );
  291. }
  292. num = newnum;
  293. }
  294. /*
  295. ================
  296. idList<_type_,_tag_>::SetGranularity
  297. Sets the base size of the array and resizes the array to match.
  298. ================
  299. */
  300. template< typename _type_, memTag_t _tag_ >
  301. ID_INLINE void idList<_type_,_tag_>::SetGranularity( int newgranularity ) {
  302. int newsize;
  303. assert( newgranularity > 0 );
  304. granularity = newgranularity;
  305. if ( list ) {
  306. // resize it to the closest level of granularity
  307. newsize = num + granularity - 1;
  308. newsize -= newsize % granularity;
  309. if ( newsize != size ) {
  310. Resize( newsize );
  311. }
  312. }
  313. }
  314. /*
  315. ================
  316. idList<_type_,_tag_>::GetGranularity
  317. Get the current granularity.
  318. ================
  319. */
  320. template< typename _type_, memTag_t _tag_ >
  321. ID_INLINE int idList<_type_,_tag_>::GetGranularity() const {
  322. return granularity;
  323. }
  324. /*
  325. ================
  326. idList<_type_,_tag_>::Condense
  327. Resizes the array to exactly the number of elements it contains or frees up memory if empty.
  328. ================
  329. */
  330. template< typename _type_, memTag_t _tag_ >
  331. ID_INLINE void idList<_type_,_tag_>::Condense() {
  332. if ( list ) {
  333. if ( num ) {
  334. Resize( num );
  335. } else {
  336. Clear();
  337. }
  338. }
  339. }
  340. /*
  341. ================
  342. idList<_type_,_tag_>::Resize
  343. Allocates memory for the amount of elements requested while keeping the contents intact.
  344. Contents are copied using their = operator so that data is correnctly instantiated.
  345. ================
  346. */
  347. template< typename _type_, memTag_t _tag_ >
  348. ID_INLINE void idList<_type_,_tag_>::Resize( int newsize ) {
  349. assert( newsize >= 0 );
  350. // free up the list if no data is being reserved
  351. if ( newsize <= 0 ) {
  352. Clear();
  353. return;
  354. }
  355. if ( newsize == size ) {
  356. // not changing the size, so just exit
  357. return;
  358. }
  359. list = (_type_ *)idListArrayResize< _type_, _tag_ >( list, size, newsize, false );
  360. size = newsize;
  361. if ( size < num ) {
  362. num = size;
  363. }
  364. }
  365. /*
  366. ================
  367. idList<_type_,_tag_>::Resize
  368. Allocates memory for the amount of elements requested while keeping the contents intact.
  369. Contents are copied using their = operator so that data is correnctly instantiated.
  370. ================
  371. */
  372. template< typename _type_, memTag_t _tag_ >
  373. ID_INLINE void idList<_type_,_tag_>::Resize( int newsize, int newgranularity ) {
  374. assert( newsize >= 0 );
  375. assert( newgranularity > 0 );
  376. granularity = newgranularity;
  377. // free up the list if no data is being reserved
  378. if ( newsize <= 0 ) {
  379. Clear();
  380. return;
  381. }
  382. list = (_type_ *)idListArrayResize< _type_, _tag_ >( list, size, newsize, false );
  383. size = newsize;
  384. if ( size < num ) {
  385. num = size;
  386. }
  387. }
  388. /*
  389. ================
  390. idList<_type_,_tag_>::AssureSize
  391. Makes sure the list has at least the given number of elements.
  392. ================
  393. */
  394. template< typename _type_, memTag_t _tag_ >
  395. ID_INLINE void idList<_type_,_tag_>::AssureSize( int newSize ) {
  396. int newNum = newSize;
  397. if ( newSize > size ) {
  398. if ( granularity == 0 ) { // this is a hack to fix our memset classes
  399. granularity = 16;
  400. }
  401. newSize += granularity - 1;
  402. newSize -= newSize % granularity;
  403. Resize( newSize );
  404. }
  405. num = newNum;
  406. }
  407. /*
  408. ================
  409. idList<_type_,_tag_>::AssureSize
  410. Makes sure the list has at least the given number of elements and initialize any elements not yet initialized.
  411. ================
  412. */
  413. template< typename _type_, memTag_t _tag_ >
  414. ID_INLINE void idList<_type_,_tag_>::AssureSize( int newSize, const _type_ &initValue ) {
  415. int newNum = newSize;
  416. if ( newSize > size ) {
  417. if ( granularity == 0 ) { // this is a hack to fix our memset classes
  418. granularity = 16;
  419. }
  420. newSize += granularity - 1;
  421. newSize -= newSize % granularity;
  422. num = size;
  423. Resize( newSize );
  424. for ( int i = num; i < newSize; i++ ) {
  425. list[i] = initValue;
  426. }
  427. }
  428. num = newNum;
  429. }
  430. /*
  431. ================
  432. idList<_type_,_tag_>::AssureSizeAlloc
  433. Makes sure the list has at least the given number of elements and allocates any elements using the allocator.
  434. NOTE: This function can only be called on lists containing pointers. Calling it
  435. on non-pointer lists will cause a compiler error.
  436. ================
  437. */
  438. template< typename _type_, memTag_t _tag_ >
  439. ID_INLINE void idList<_type_,_tag_>::AssureSizeAlloc( int newSize, new_t *allocator ) {
  440. int newNum = newSize;
  441. if ( newSize > size ) {
  442. if ( granularity == 0 ) { // this is a hack to fix our memset classes
  443. granularity = 16;
  444. }
  445. newSize += granularity - 1;
  446. newSize -= newSize % granularity;
  447. num = size;
  448. Resize( newSize );
  449. for ( int i = num; i < newSize; i++ ) {
  450. list[i] = (*allocator)();
  451. }
  452. }
  453. num = newNum;
  454. }
  455. /*
  456. ================
  457. idList<_type_,_tag_>::operator=
  458. Copies the contents and size attributes of another list.
  459. ================
  460. */
  461. template< typename _type_, memTag_t _tag_ >
  462. ID_INLINE idList<_type_,_tag_> & idList<_type_,_tag_>::operator=( const idList<_type_,_tag_> &other ) {
  463. int i;
  464. Clear();
  465. num = other.num;
  466. size = other.size;
  467. granularity = other.granularity;
  468. memTag = other.memTag;
  469. if ( size ) {
  470. list = (_type_ *)idListArrayNew< _type_, _tag_ >( size, false );
  471. for( i = 0; i < num; i++ ) {
  472. list[ i ] = other.list[ i ];
  473. }
  474. }
  475. return *this;
  476. }
  477. /*
  478. ================
  479. idList<_type_,_tag_>::operator[] const
  480. Access operator. Index must be within range or an assert will be issued in debug builds.
  481. Release builds do no range checking.
  482. ================
  483. */
  484. template< typename _type_, memTag_t _tag_ >
  485. ID_INLINE const _type_ & idList<_type_,_tag_>::operator[]( int index ) const {
  486. assert( index >= 0 );
  487. assert( index < num );
  488. return list[ index ];
  489. }
  490. /*
  491. ================
  492. idList<_type_,_tag_>::operator[]
  493. Access operator. Index must be within range or an assert will be issued in debug builds.
  494. Release builds do no range checking.
  495. ================
  496. */
  497. template< typename _type_, memTag_t _tag_ >
  498. ID_INLINE _type_ & idList<_type_,_tag_>::operator[]( int index ) {
  499. assert( index >= 0 );
  500. assert( index < num );
  501. return list[ index ];
  502. }
  503. /*
  504. ================
  505. idList<_type_,_tag_>::Ptr
  506. Returns a pointer to the begining of the array. Useful for iterating through the list in loops.
  507. Note: may return NULL if the list is empty.
  508. FIXME: Create an iterator template for this kind of thing.
  509. ================
  510. */
  511. template< typename _type_, memTag_t _tag_ >
  512. ID_INLINE _type_ * idList<_type_,_tag_>::Ptr() {
  513. return list;
  514. }
  515. /*
  516. ================
  517. idList<_type_,_tag_>::Ptr
  518. Returns a pointer to the begining of the array. Useful for iterating through the list in loops.
  519. Note: may return NULL if the list is empty.
  520. FIXME: Create an iterator template for this kind of thing.
  521. ================
  522. */
  523. template< typename _type_, memTag_t _tag_ >
  524. const ID_INLINE _type_ * idList<_type_,_tag_>::Ptr() const {
  525. return list;
  526. }
  527. /*
  528. ================
  529. idList<_type_,_tag_>::Alloc
  530. Returns a reference to a new data element at the end of the list.
  531. ================
  532. */
  533. template< typename _type_, memTag_t _tag_ >
  534. ID_INLINE _type_ & idList<_type_,_tag_>::Alloc() {
  535. if ( !list ) {
  536. Resize( granularity );
  537. }
  538. if ( num == size ) {
  539. Resize( size + granularity );
  540. }
  541. return list[ num++ ];
  542. }
  543. /*
  544. ================
  545. idList<_type_,_tag_>::Append
  546. Increases the size of the list by one element and copies the supplied data into it.
  547. Returns the index of the new element.
  548. ================
  549. */
  550. template< typename _type_, memTag_t _tag_ >
  551. ID_INLINE int idList<_type_,_tag_>::Append( _type_ const & obj ) {
  552. if ( !list ) {
  553. Resize( granularity );
  554. }
  555. if ( num == size ) {
  556. int newsize;
  557. if ( granularity == 0 ) { // this is a hack to fix our memset classes
  558. granularity = 16;
  559. }
  560. newsize = size + granularity;
  561. Resize( newsize - newsize % granularity );
  562. }
  563. list[ num ] = obj;
  564. num++;
  565. return num - 1;
  566. }
  567. /*
  568. ================
  569. idList<_type_,_tag_>::Insert
  570. Increases the size of the list by at leat one element if necessary
  571. and inserts the supplied data into it.
  572. Returns the index of the new element.
  573. ================
  574. */
  575. template< typename _type_, memTag_t _tag_ >
  576. ID_INLINE int idList<_type_,_tag_>::Insert( _type_ const & obj, int index ) {
  577. if ( !list ) {
  578. Resize( granularity );
  579. }
  580. if ( num == size ) {
  581. int newsize;
  582. if ( granularity == 0 ) { // this is a hack to fix our memset classes
  583. granularity = 16;
  584. }
  585. newsize = size + granularity;
  586. Resize( newsize - newsize % granularity );
  587. }
  588. if ( index < 0 ) {
  589. index = 0;
  590. }
  591. else if ( index > num ) {
  592. index = num;
  593. }
  594. for ( int i = num; i > index; --i ) {
  595. list[i] = list[i-1];
  596. }
  597. num++;
  598. list[index] = obj;
  599. return index;
  600. }
  601. /*
  602. ================
  603. idList<_type_,_tag_>::Append
  604. adds the other list to this one
  605. Returns the size of the new combined list
  606. ================
  607. */
  608. template< typename _type_, memTag_t _tag_ >
  609. ID_INLINE int idList<_type_,_tag_>::Append( const idList< _type_, _tag_ > &other ) {
  610. if ( !list ) {
  611. if ( granularity == 0 ) { // this is a hack to fix our memset classes
  612. granularity = 16;
  613. }
  614. Resize( granularity );
  615. }
  616. int n = other.Num();
  617. for (int i = 0; i < n; i++) {
  618. Append(other[i]);
  619. }
  620. return Num();
  621. }
  622. /*
  623. ================
  624. idList<_type_,_tag_>::AddUnique
  625. Adds the data to the list if it doesn't already exist. Returns the index of the data in the list.
  626. ================
  627. */
  628. template< typename _type_, memTag_t _tag_ >
  629. ID_INLINE int idList<_type_,_tag_>::AddUnique( _type_ const & obj ) {
  630. int index;
  631. index = FindIndex( obj );
  632. if ( index < 0 ) {
  633. index = Append( obj );
  634. }
  635. return index;
  636. }
  637. /*
  638. ================
  639. idList<_type_,_tag_>::FindIndex
  640. Searches for the specified data in the list and returns it's index. Returns -1 if the data is not found.
  641. ================
  642. */
  643. template< typename _type_, memTag_t _tag_ >
  644. ID_INLINE int idList<_type_,_tag_>::FindIndex( _type_ const & obj ) const {
  645. int i;
  646. for( i = 0; i < num; i++ ) {
  647. if ( list[ i ] == obj ) {
  648. return i;
  649. }
  650. }
  651. // Not found
  652. return -1;
  653. }
  654. /*
  655. ================
  656. idList<_type_,_tag_>::Find
  657. Searches for the specified data in the list and returns it's address. Returns NULL if the data is not found.
  658. ================
  659. */
  660. template< typename _type_, memTag_t _tag_ >
  661. ID_INLINE _type_ *idList<_type_,_tag_>::Find( _type_ const & obj ) const {
  662. int i;
  663. i = FindIndex( obj );
  664. if ( i >= 0 ) {
  665. return &list[ i ];
  666. }
  667. return NULL;
  668. }
  669. /*
  670. ================
  671. idList<_type_,_tag_>::FindNull
  672. Searches for a NULL pointer in the list. Returns -1 if NULL is not found.
  673. NOTE: This function can only be called on lists containing pointers. Calling it
  674. on non-pointer lists will cause a compiler error.
  675. ================
  676. */
  677. template< typename _type_, memTag_t _tag_ >
  678. ID_INLINE int idList<_type_,_tag_>::FindNull() const {
  679. int i;
  680. for( i = 0; i < num; i++ ) {
  681. if ( list[ i ] == NULL ) {
  682. return i;
  683. }
  684. }
  685. // Not found
  686. return -1;
  687. }
  688. /*
  689. ================
  690. idList<_type_,_tag_>::IndexOf
  691. Takes a pointer to an element in the list and returns the index of the element.
  692. This is NOT a guarantee that the object is really in the list.
  693. Function will assert in debug builds if pointer is outside the bounds of the list,
  694. but remains silent in release builds.
  695. ================
  696. */
  697. template< typename _type_, memTag_t _tag_ >
  698. ID_INLINE int idList<_type_,_tag_>::IndexOf( _type_ const *objptr ) const {
  699. int index;
  700. index = objptr - list;
  701. assert( index >= 0 );
  702. assert( index < num );
  703. return index;
  704. }
  705. /*
  706. ================
  707. idList<_type_,_tag_>::RemoveIndex
  708. Removes the element at the specified index and moves all data following the element down to fill in the gap.
  709. The number of elements in the list is reduced by one. Returns false if the index is outside the bounds of the list.
  710. Note that the element is not destroyed, so any memory used by it may not be freed until the destruction of the list.
  711. ================
  712. */
  713. template< typename _type_, memTag_t _tag_ >
  714. ID_INLINE bool idList<_type_,_tag_>::RemoveIndex( int index ) {
  715. int i;
  716. assert( list != NULL );
  717. assert( index >= 0 );
  718. assert( index < num );
  719. if ( ( index < 0 ) || ( index >= num ) ) {
  720. return false;
  721. }
  722. num--;
  723. for( i = index; i < num; i++ ) {
  724. list[ i ] = list[ i + 1 ];
  725. }
  726. return true;
  727. }
  728. /*
  729. ========================
  730. idList<_type_,_tag_>::RemoveIndexFast
  731. Removes the element at the specified index and moves the last element into its spot, rather
  732. than moving the whole array down by one. Of course, this doesn't maintain the order of
  733. elements! The number of elements in the list is reduced by one.
  734. return: bool - false if the data is not found in the list.
  735. NOTE: The element is not destroyed, so any memory used by it may not be freed until the
  736. destruction of the list.
  737. ========================
  738. */
  739. template< typename _type_, memTag_t _tag_ >
  740. ID_INLINE bool idList<_type_,_tag_>::RemoveIndexFast( int index ) {
  741. if ( ( index < 0 ) || ( index >= num ) ) {
  742. return false;
  743. }
  744. num--;
  745. if ( index != num ) {
  746. list[ index ] = list[ num ];
  747. }
  748. return true;
  749. }
  750. /*
  751. ================
  752. idList<_type_,_tag_>::Remove
  753. Removes the element if it is found within the list and moves all data following the element down to fill in the gap.
  754. The number of elements in the list is reduced by one. Returns false if the data is not found in the list. Note that
  755. the element is not destroyed, so any memory used by it may not be freed until the destruction of the list.
  756. ================
  757. */
  758. template< typename _type_, memTag_t _tag_ >
  759. ID_INLINE bool idList<_type_,_tag_>::Remove( _type_ const & obj ) {
  760. int index;
  761. index = FindIndex( obj );
  762. if ( index >= 0 ) {
  763. return RemoveIndex( index );
  764. }
  765. return false;
  766. }
  767. //
  768. ///*
  769. //================
  770. //idList<_type_,_tag_>::Sort
  771. //
  772. //Performs a qsort on the list using the supplied comparison function. Note that the data is merely moved around the
  773. //list, so any pointers to data within the list may no longer be valid.
  774. //================
  775. //*/
  776. //template< typename _type_, memTag_t _tag_ >
  777. //ID_INLINE void idList<_type_,_tag_>::Sort( cmp_t *compare ) {
  778. // if ( !list ) {
  779. // return;
  780. // }
  781. // typedef int cmp_c(const void *, const void *);
  782. //
  783. // cmp_c *vCompare = (cmp_c *)compare;
  784. // qsort( ( void * )list, ( size_t )num, sizeof( _type_ ), vCompare );
  785. //}
  786. /*
  787. ========================
  788. idList<_type_,_tag_>::SortWithTemplate
  789. Performs a QuickSort on the list using the supplied sort algorithm.
  790. Note: The data is merely moved around the list, so any pointers to data within the list may
  791. no longer be valid.
  792. ========================
  793. */
  794. template< typename _type_, memTag_t _tag_ >
  795. ID_INLINE void idList<_type_,_tag_>::SortWithTemplate( const idSort<_type_> & sort ) {
  796. if ( list == NULL ) {
  797. return;
  798. }
  799. sort.Sort( Ptr(), Num() );
  800. }
  801. //
  802. ///*
  803. //================
  804. //idList<_type_,_tag_>::SortSubSection
  805. //
  806. //Sorts a subsection of the list.
  807. //================
  808. //*/
  809. //template< typename _type_, memTag_t _tag_ >
  810. //ID_INLINE void idList<_type_,_tag_>::SortSubSection( int startIndex, int endIndex, cmp_t *compare ) {
  811. // if ( !list ) {
  812. // return;
  813. // }
  814. // if ( startIndex < 0 ) {
  815. // startIndex = 0;
  816. // }
  817. // if ( endIndex >= num ) {
  818. // endIndex = num - 1;
  819. // }
  820. // if ( startIndex >= endIndex ) {
  821. // return;
  822. // }
  823. // typedef int cmp_c(const void *, const void *);
  824. //
  825. // cmp_c *vCompare = (cmp_c *)compare;
  826. // qsort( ( void * )( &list[startIndex] ), ( size_t )( endIndex - startIndex + 1 ), sizeof( _type_ ), vCompare );
  827. //}
  828. /*
  829. ========================
  830. FindFromGeneric
  831. Finds an item in a list based on any another datatype. Your _type_ must overload operator()== for the _type_.
  832. If your _type_ is a ptr, use the FindFromGenericPtr function instead.
  833. ========================
  834. */
  835. template< typename _type_, memTag_t _tag_, typename _compare_type_ >
  836. _type_ * FindFromGeneric( idList<_type_, _tag_> & list, const _compare_type_ & other ) {
  837. for ( int i = 0; i < list.Num(); i++ ) {
  838. if ( list[ i ] == other ) {
  839. return &list[ i ];
  840. }
  841. }
  842. return NULL;
  843. }
  844. /*
  845. ========================
  846. FindFromGenericPtr
  847. ========================
  848. */
  849. template< typename _type_, memTag_t _tag_, typename _compare_type_ >
  850. _type_ * FindFromGenericPtr( idList<_type_, _tag_> & list, const _compare_type_ & other ) {
  851. for ( int i = 0; i < list.Num(); i++ ) {
  852. if ( *list[ i ] == other ) {
  853. return &list[ i ];
  854. }
  855. }
  856. return NULL;
  857. }
  858. #endif /* !__LIST_H__ */