Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

272 lines
6.2 KiB

  1. //====== Copyright � 1996-2009, Valve Corporation, All rights reserved. =======//
  2. #ifndef INCREMENTAL_VECTOR_H
  3. #define INCREMENTAL_VECTOR_H
  4. // this class facilitates an array of pointers that get added and removed frequently;
  5. // it's intrusive: the class that is pointed to must contain and maintain an index
  6. #include "tier1/utlvector.h"
  7. template < class CLASS >
  8. struct DefaultIncrementalVectorAccessor_t
  9. {
  10. static int GetIndex( const CLASS * p ) { return p->m_nIncrementalVectorIndex; }
  11. static void SetIndex( CLASS * p, int nIndex ) { p->m_nIncrementalVectorIndex = nIndex; }
  12. };
  13. template <class T, class Accessor = DefaultIncrementalVectorAccessor_t< T > , class Allocator = CUtlMemory< T* > >
  14. class CUtlIncrementalVector
  15. {
  16. public:
  17. T** Base(){ return m_data.Base(); }
  18. T*const* Base()const{ return m_data.Base(); }
  19. typedef T* ElemType_t;
  20. typedef T** iterator;
  21. typedef T*const* const_iterator;
  22. enum { IsUtlVector = true }; // Used to match this at compiletime
  23. iterator begin() { return Base(); }
  24. const_iterator begin() const { return Base(); }
  25. iterator end() { return Base() + Count(); }
  26. const_iterator end() const { return Base() + Count(); }
  27. void SetCountAndCreateOrDelete( int nNewCount )
  28. {
  29. int nOldCount = Count();
  30. for( int i = nNewCount; i < nOldCount; ++i )
  31. {
  32. delete m_data[i];
  33. }
  34. m_data.SetCount( nNewCount );
  35. for( int i = nOldCount; i < nNewCount; ++i )
  36. {
  37. m_data[i] = new T;
  38. Accessor::SetIndex( m_data[i], i );
  39. }
  40. Validate();
  41. }
  42. int Count() const
  43. {
  44. return m_data.Count();
  45. }
  46. T* operator[]( int i )
  47. {
  48. Assert( !m_data[i] || Accessor::GetIndex( m_data[i] ) == i );
  49. return m_data[i];
  50. }
  51. const T* operator[]( int i )const
  52. {
  53. Assert( !m_data[i] || Accessor::GetIndex( m_data[i] ) == i );
  54. return m_data[i];
  55. }
  56. void SetElementToNull( int i )
  57. {
  58. m_data[ i ] = NULL;
  59. }
  60. T* AddToTail( T* p )
  61. {
  62. Validate();
  63. Accessor::SetIndex( p, m_data.Count() );
  64. m_data.AddToTail( p );
  65. Validate();
  66. return p;
  67. }
  68. void MoveToHead( T *pMid )
  69. {
  70. Validate();
  71. int nMidIndex = Accessor::GetIndex( pMid );
  72. Accessor::SetIndex( pMid, 0 );
  73. T *pHead = m_data[0];
  74. Accessor::SetIndex( pHead, nMidIndex );
  75. m_data[0] = pMid;
  76. m_data[nMidIndex] = pHead;
  77. Validate();
  78. }
  79. void SwapItems( int i1, int i2 )
  80. {
  81. Validate();
  82. T *p1 = m_data[i1];
  83. T *p2 = m_data[i2];
  84. Accessor::SetIndex( p1, i2 );
  85. Accessor::SetIndex( p2, i1 );
  86. m_data[i1] = p2;
  87. m_data[i2] = p1;
  88. Validate();
  89. }
  90. void InsertNewMultipleBefore( int nIndex, int nCount )
  91. {
  92. if( nCount )
  93. {
  94. for( int i = nIndex; i < m_data.Count(); ++i )
  95. {
  96. T *pElement = m_data[i];
  97. Accessor::SetIndex( pElement, Accessor::GetIndex( pElement ) + nCount );
  98. }
  99. m_data.InsertMultipleBefore( nIndex, nCount );
  100. for( int i = 0; i < nCount; ++i )
  101. {
  102. T *p = new T;
  103. Accessor::SetIndex( p, nIndex + i );
  104. m_data[ nIndex + i ] = p;
  105. }
  106. }
  107. }
  108. void RemoveAndDeleteMultiple( int nIndex, int nCount )
  109. {
  110. if( nCount )
  111. {
  112. for( int i = nIndex, nEnd = MIN( nIndex + nCount, m_data.Count() ); i < nEnd; ++i )
  113. {
  114. delete m_data[i];
  115. }
  116. m_data.RemoveMultiple( nIndex, nCount );
  117. for ( int i = nIndex; i < m_data.Count(); ++i )
  118. {
  119. Accessor::SetIndex( m_data[ i ], i );
  120. }
  121. }
  122. }
  123. void RemoveMultiple( int nIndex, int nCount )
  124. {
  125. if ( nCount )
  126. {
  127. m_data.RemoveMultiple( nIndex, nCount );
  128. for ( int i = nIndex; i < Count(); ++i )
  129. {
  130. Accessor::SetIndex( m_data[ i ], i );
  131. }
  132. }
  133. }
  134. void RemoveMultipleFromHead( int num )
  135. {
  136. if ( num )
  137. {
  138. m_data.RemoveMultipleFromHead( num );
  139. for ( int i = 0; i < Count(); ++i )
  140. {
  141. Accessor::SetIndex( m_data[ i ], i );
  142. }
  143. }
  144. }
  145. void RemoveAndDelete( int nIndex ) ///< preserves order, shifts elements
  146. {
  147. if( nIndex < Count() )
  148. {
  149. delete m_data[nIndex];
  150. for( int i = nIndex + 1; i < Count(); ++i )
  151. {
  152. Accessor::SetIndex( m_data[ i ], i - 1 );
  153. m_data[ i - 1 ] = m_data[ i ];
  154. }
  155. m_data.RemoveMultipleFromTail( 1 );
  156. }
  157. }
  158. void FastRemove( int elem ) // doesn't preserve order
  159. {
  160. Validate();
  161. //T* pDeletable = m_data[elem];
  162. T* pLast = m_data.Tail(); // Optimization Warning: pLast and pDelete pointers are aliased
  163. m_data[elem] = pLast;
  164. m_data.RemoveMultipleFromTail( 1 );
  165. Accessor::SetIndex( pLast, elem );
  166. // Accessor::SetIndex( pDeletable, -1 ); // this is not really necessary, except for debugging; there's also a danger that client deleted the object before calling FastRemove
  167. Validate();
  168. }
  169. T* FindAndFastRemove( T* p ) // removes first occurrence of src, doesn't preserve order
  170. {
  171. int nIndex = Accessor::GetIndex( p );
  172. Assert( m_data[nIndex] == p );
  173. FastRemove( nIndex );
  174. return p;
  175. }
  176. int Find( const T* p )const
  177. {
  178. int nIndex = Accessor::GetIndex( p );
  179. if ( uint( nIndex ) < uint( Count() ) && m_data[ nIndex ] == p )
  180. return nIndex;
  181. else
  182. return -1;
  183. }
  184. bool Has( const T *p )const
  185. {
  186. int nIndex = Accessor::GetIndex( p );
  187. return uint( nIndex ) < uint( Count() ) && m_data[ nIndex ] == p;
  188. }
  189. void FastRemoveAndDelete( T* p )
  190. {
  191. int nIndex = Accessor::GetIndex( p );
  192. FastRemove( nIndex );
  193. delete p;
  194. }
  195. void PurgeAndDeleteElements()
  196. {
  197. Validate();
  198. m_data.PurgeAndDeleteElements();
  199. }
  200. inline void Validate()
  201. {
  202. #if defined( DBGFLAG_ASSERT ) && defined( _DEBUG )
  203. for( int i =0 ;i < Count(); ++i )
  204. {
  205. Assert( !m_data[i] || Accessor::GetIndex( m_data[i] ) == i );
  206. }
  207. #endif
  208. }
  209. void Purge()
  210. {
  211. m_data.Purge();
  212. }
  213. bool IsEmpty()const
  214. {
  215. return m_data.IsEmpty();
  216. }
  217. T *Tail()
  218. {
  219. return m_data.Tail();
  220. }
  221. void EnsureCapacity( int nCap )
  222. {
  223. m_data.EnsureCapacity( nCap );
  224. }
  225. void Sort( int (__cdecl *pfnCompare)(const ElemType_t *, const ElemType_t *) )
  226. {
  227. m_data.Sort( pfnCompare );
  228. for( int i = 0; i < m_data.Count(); ++i )
  229. {
  230. Accessor::SetIndex( m_data[i], i );
  231. }
  232. }
  233. protected:
  234. CUtlVector< T*, Allocator > m_data;
  235. };
  236. #define DECLARE_INCREMENTAL_VECTOR_TYPE(CLASS, MEMBER) \
  237. struct CLASS##_##NAME##_IncrementalVectorAccessor_t \
  238. { \
  239. static int GetIndex( const CLASS * p ) { return p->MEMBER; } \
  240. static void SetIndex( const CLASS * p, int nIndex ) { p->MEMBER = nIndex; } \
  241. }; \
  242. typedef CUtlIncrementalVector < CLASS, CLASS##_##NAME##_IncrementalVectorAccessor_t >
  243. #endif