Team Fortress 2 Source Code as on 22/4/2020
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.

1275 lines
32 KiB

  1. //====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. // A growable array class that maintains a free list and keeps elements
  8. // in the same location
  9. //=============================================================================//
  10. #ifndef UTLVECTOR_H
  11. #define UTLVECTOR_H
  12. #ifdef _WIN32
  13. #pragma once
  14. #endif
  15. #include <string.h>
  16. #include "tier0/platform.h"
  17. #include "tier0/dbg.h"
  18. #include "tier0/threadtools.h"
  19. #include "tier1/utlmemory.h"
  20. #include "tier1/utlblockmemory.h"
  21. #include "tier1/strtools.h"
  22. #define FOR_EACH_VEC( vecName, iteratorName ) \
  23. for ( int iteratorName = 0; iteratorName < (vecName).Count(); iteratorName++ )
  24. #define FOR_EACH_VEC_BACK( vecName, iteratorName ) \
  25. for ( int iteratorName = (vecName).Count()-1; iteratorName >= 0; iteratorName-- )
  26. //-----------------------------------------------------------------------------
  27. // The CUtlVector class:
  28. // A growable array class which doubles in size by default.
  29. // It will always keep all elements consecutive in memory, and may move the
  30. // elements around in memory (via a PvRealloc) when elements are inserted or
  31. // removed. Clients should therefore refer to the elements of the vector
  32. // by index (they should *never* maintain pointers to elements in the vector).
  33. //-----------------------------------------------------------------------------
  34. template< class T, class A = CUtlMemory<T> >
  35. class CUtlVector
  36. {
  37. typedef A CAllocator;
  38. public:
  39. typedef T ElemType_t;
  40. // constructor, destructor
  41. CUtlVector( int growSize = 0, int initSize = 0 );
  42. CUtlVector( T* pMemory, int allocationCount, int numElements = 0 );
  43. ~CUtlVector();
  44. // Copy the array.
  45. CUtlVector<T, A>& operator=( const CUtlVector<T, A> &other );
  46. // element access
  47. T& operator[]( int i );
  48. const T& operator[]( int i ) const;
  49. T& Element( int i );
  50. const T& Element( int i ) const;
  51. T& Head();
  52. const T& Head() const;
  53. T& Tail();
  54. const T& Tail() const;
  55. // Gets the base address (can change when adding elements!)
  56. T* Base() { return m_Memory.Base(); }
  57. const T* Base() const { return m_Memory.Base(); }
  58. // Returns the number of elements in the vector
  59. int Count() const;
  60. // Is element index valid?
  61. bool IsValidIndex( int i ) const;
  62. static int InvalidIndex();
  63. // Adds an element, uses default constructor
  64. int AddToHead();
  65. int AddToTail();
  66. int InsertBefore( int elem );
  67. int InsertAfter( int elem );
  68. // Adds an element, uses copy constructor
  69. int AddToHead( const T& src );
  70. int AddToTail( const T& src );
  71. int InsertBefore( int elem, const T& src );
  72. int InsertAfter( int elem, const T& src );
  73. // Adds multiple elements, uses default constructor
  74. int AddMultipleToHead( int num );
  75. int AddMultipleToTail( int num );
  76. int AddMultipleToTail( int num, const T *pToCopy );
  77. int InsertMultipleBefore( int elem, int num );
  78. int InsertMultipleBefore( int elem, int num, const T *pToCopy );
  79. int InsertMultipleAfter( int elem, int num );
  80. // Calls RemoveAll() then AddMultipleToTail.
  81. void SetSize( int size );
  82. void SetCount( int count );
  83. void SetCountNonDestructively( int count ); //sets count by adding or removing elements to tail TODO: This should probably be the default behavior for SetCount
  84. // Calls SetSize and copies each element.
  85. void CopyArray( const T *pArray, int size );
  86. // Fast swap
  87. void Swap( CUtlVector< T, A > &vec );
  88. // Add the specified array to the tail.
  89. int AddVectorToTail( CUtlVector<T, A> const &src );
  90. // Finds an element (element needs operator== defined)
  91. int Find( const T& src ) const;
  92. void FillWithValue( const T& src );
  93. bool HasElement( const T& src ) const;
  94. // Makes sure we have enough memory allocated to store a requested # of elements
  95. void EnsureCapacity( int num );
  96. // Makes sure we have at least this many elements
  97. void EnsureCount( int num );
  98. // Element removal
  99. void FastRemove( int elem ); // doesn't preserve order
  100. void Remove( int elem ); // preserves order, shifts elements
  101. bool FindAndRemove( const T& src ); // removes first occurrence of src, preserves order, shifts elements
  102. bool FindAndFastRemove( const T& src ); // removes first occurrence of src, doesn't preserve order
  103. void RemoveMultiple( int elem, int num ); // preserves order, shifts elements
  104. void RemoveMultipleFromHead(int num); // removes num elements from tail
  105. void RemoveMultipleFromTail(int num); // removes num elements from tail
  106. void RemoveAll(); // doesn't deallocate memory
  107. // Memory deallocation
  108. void Purge();
  109. // Purges the list and calls delete on each element in it.
  110. void PurgeAndDeleteElements();
  111. // Compacts the vector to the number of elements actually in use
  112. void Compact();
  113. // Set the size by which it grows when it needs to allocate more memory.
  114. void SetGrowSize( int size ) { m_Memory.SetGrowSize( size ); }
  115. int NumAllocated() const; // Only use this if you really know what you're doing!
  116. void Sort( int (__cdecl *pfnCompare)(const T *, const T *) );
  117. // Call this to quickly sort non-contiguously allocated vectors
  118. void InPlaceQuickSort( int (__cdecl *pfnCompare)(const T *, const T *) );
  119. #ifdef DBGFLAG_VALIDATE
  120. void Validate( CValidator &validator, char *pchName ); // Validate our internal structures
  121. #endif // DBGFLAG_VALIDATE
  122. protected:
  123. // Can't copy this unless we explicitly do it!
  124. CUtlVector( CUtlVector const& vec ) { Assert(0); }
  125. // Grows the vector
  126. void GrowVector( int num = 1 );
  127. // Shifts elements....
  128. void ShiftElementsRight( int elem, int num = 1 );
  129. void ShiftElementsLeft( int elem, int num = 1 );
  130. CAllocator m_Memory;
  131. int m_Size;
  132. #ifndef _X360
  133. // For easier access to the elements through the debugger
  134. // it's in release builds so this can be used in libraries correctly
  135. T *m_pElements;
  136. inline void ResetDbgInfo()
  137. {
  138. m_pElements = Base();
  139. }
  140. #else
  141. inline void ResetDbgInfo() {}
  142. #endif
  143. private:
  144. void InPlaceQuickSort_r( int (__cdecl *pfnCompare)(const T *, const T *), int nLeft, int nRight );
  145. };
  146. // this is kind of ugly, but until C++ gets templatized typedefs in C++0x, it's our only choice
  147. template < class T >
  148. class CUtlBlockVector : public CUtlVector< T, CUtlBlockMemory< T, int > >
  149. {
  150. public:
  151. CUtlBlockVector( int growSize = 0, int initSize = 0 )
  152. : CUtlVector< T, CUtlBlockMemory< T, int > >( growSize, initSize ) {}
  153. };
  154. //-----------------------------------------------------------------------------
  155. // The CUtlVectorMT class:
  156. // An array class with spurious mutex protection. Nothing is actually protected
  157. // unless you call Lock and Unlock. Also, the Mutex_t is actually not a type
  158. // but a member which probably isn't used.
  159. //-----------------------------------------------------------------------------
  160. template< class BASE_UTLVECTOR, class MUTEX_TYPE = CThreadFastMutex >
  161. class CUtlVectorMT : public BASE_UTLVECTOR, public MUTEX_TYPE
  162. {
  163. typedef BASE_UTLVECTOR BaseClass;
  164. public:
  165. // MUTEX_TYPE Mutex_t;
  166. // constructor, destructor
  167. CUtlVectorMT( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {}
  168. CUtlVectorMT( typename BaseClass::ElemType_t* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {}
  169. };
  170. //-----------------------------------------------------------------------------
  171. // The CUtlVectorFixed class:
  172. // A array class with a fixed allocation scheme
  173. //-----------------------------------------------------------------------------
  174. template< class T, size_t MAX_SIZE >
  175. class CUtlVectorFixed : public CUtlVector< T, CUtlMemoryFixed<T, MAX_SIZE > >
  176. {
  177. typedef CUtlVector< T, CUtlMemoryFixed<T, MAX_SIZE > > BaseClass;
  178. public:
  179. // constructor, destructor
  180. CUtlVectorFixed( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {}
  181. CUtlVectorFixed( T* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {}
  182. };
  183. //-----------------------------------------------------------------------------
  184. // The CUtlVectorFixedGrowable class:
  185. // A array class with a fixed allocation scheme backed by a dynamic one
  186. //-----------------------------------------------------------------------------
  187. template< class T, size_t MAX_SIZE >
  188. class CUtlVectorFixedGrowable : public CUtlVector< T, CUtlMemoryFixedGrowable<T, MAX_SIZE > >
  189. {
  190. typedef CUtlVector< T, CUtlMemoryFixedGrowable<T, MAX_SIZE > > BaseClass;
  191. public:
  192. // constructor, destructor
  193. CUtlVectorFixedGrowable( int growSize = 0 ) : BaseClass( growSize, MAX_SIZE ) {}
  194. };
  195. //-----------------------------------------------------------------------------
  196. // The CUtlVectorConservative class:
  197. // A array class with a conservative allocation scheme
  198. //-----------------------------------------------------------------------------
  199. template< class T >
  200. class CUtlVectorConservative : public CUtlVector< T, CUtlMemoryConservative<T> >
  201. {
  202. typedef CUtlVector< T, CUtlMemoryConservative<T> > BaseClass;
  203. public:
  204. // constructor, destructor
  205. CUtlVectorConservative( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {}
  206. CUtlVectorConservative( T* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {}
  207. };
  208. //-----------------------------------------------------------------------------
  209. // The CUtlVectorUltra Conservative class:
  210. // A array class with a very conservative allocation scheme, with customizable allocator
  211. // Especialy useful if you have a lot of vectors that are sparse, or if you're
  212. // carefully packing holders of vectors
  213. //-----------------------------------------------------------------------------
  214. #pragma warning(push)
  215. #pragma warning(disable : 4200) // warning C4200: nonstandard extension used : zero-sized array in struct/union
  216. #pragma warning(disable : 4815 ) // warning C4815: 'staticData' : zero-sized array in stack object will have no elements
  217. class CUtlVectorUltraConservativeAllocator
  218. {
  219. public:
  220. static void *Alloc( size_t nSize )
  221. {
  222. return malloc( nSize );
  223. }
  224. static void *Realloc( void *pMem, size_t nSize )
  225. {
  226. return realloc( pMem, nSize );
  227. }
  228. static void Free( void *pMem )
  229. {
  230. free( pMem );
  231. }
  232. static size_t GetSize( void *pMem )
  233. {
  234. return mallocsize( pMem );
  235. }
  236. };
  237. template <typename T, typename A = CUtlVectorUltraConservativeAllocator >
  238. class CUtlVectorUltraConservative : private A
  239. {
  240. public:
  241. CUtlVectorUltraConservative()
  242. {
  243. m_pData = StaticData();
  244. }
  245. ~CUtlVectorUltraConservative()
  246. {
  247. RemoveAll();
  248. }
  249. int Count() const
  250. {
  251. return m_pData->m_Size;
  252. }
  253. static int InvalidIndex()
  254. {
  255. return -1;
  256. }
  257. inline bool IsValidIndex( int i ) const
  258. {
  259. return (i >= 0) && (i < Count());
  260. }
  261. T& operator[]( int i )
  262. {
  263. Assert( IsValidIndex( i ) );
  264. return m_pData->m_Elements[i];
  265. }
  266. const T& operator[]( int i ) const
  267. {
  268. Assert( IsValidIndex( i ) );
  269. return m_pData->m_Elements[i];
  270. }
  271. T& Element( int i )
  272. {
  273. Assert( IsValidIndex( i ) );
  274. return m_pData->m_Elements[i];
  275. }
  276. const T& Element( int i ) const
  277. {
  278. Assert( IsValidIndex( i ) );
  279. return m_pData->m_Elements[i];
  280. }
  281. void EnsureCapacity( int num )
  282. {
  283. int nCurCount = Count();
  284. if ( num <= nCurCount )
  285. {
  286. return;
  287. }
  288. if ( m_pData == StaticData() )
  289. {
  290. m_pData = (Data_t *)A::Alloc( sizeof(int) + ( num * sizeof(T) ) );
  291. m_pData->m_Size = 0;
  292. }
  293. else
  294. {
  295. int nNeeded = sizeof(int) + ( num * sizeof(T) );
  296. int nHave = A::GetSize( m_pData );
  297. if ( nNeeded > nHave )
  298. {
  299. m_pData = (Data_t *)A::Realloc( m_pData, nNeeded );
  300. }
  301. }
  302. }
  303. int AddToTail( const T& src )
  304. {
  305. int iNew = Count();
  306. EnsureCapacity( Count() + 1 );
  307. m_pData->m_Elements[iNew] = src;
  308. m_pData->m_Size++;
  309. return iNew;
  310. }
  311. void RemoveAll()
  312. {
  313. if ( Count() )
  314. {
  315. for (int i = m_pData->m_Size; --i >= 0; )
  316. {
  317. Destruct(&m_pData->m_Elements[i]);
  318. }
  319. }
  320. if ( m_pData != StaticData() )
  321. {
  322. A::Free( m_pData );
  323. m_pData = StaticData();
  324. }
  325. }
  326. void PurgeAndDeleteElements()
  327. {
  328. if ( m_pData != StaticData() )
  329. {
  330. for( int i=0; i < m_pData->m_Size; i++ )
  331. {
  332. delete Element(i);
  333. }
  334. RemoveAll();
  335. }
  336. }
  337. void FastRemove( int elem )
  338. {
  339. Assert( IsValidIndex(elem) );
  340. Destruct( &Element(elem) );
  341. if (Count() > 0)
  342. {
  343. if ( elem != m_pData->m_Size -1 )
  344. memcpy( &Element(elem), &Element(m_pData->m_Size-1), sizeof(T) );
  345. --m_pData->m_Size;
  346. }
  347. if ( !m_pData->m_Size )
  348. {
  349. A::Free( m_pData );
  350. m_pData = StaticData();
  351. }
  352. }
  353. void Remove( int elem )
  354. {
  355. Destruct( &Element(elem) );
  356. ShiftElementsLeft(elem);
  357. --m_pData->m_Size;
  358. if ( !m_pData->m_Size )
  359. {
  360. A::Free( m_pData );
  361. m_pData = StaticData();
  362. }
  363. }
  364. int Find( const T& src ) const
  365. {
  366. int nCount = Count();
  367. for ( int i = 0; i < nCount; ++i )
  368. {
  369. if (Element(i) == src)
  370. return i;
  371. }
  372. return -1;
  373. }
  374. bool FindAndRemove( const T& src )
  375. {
  376. int elem = Find( src );
  377. if ( elem != -1 )
  378. {
  379. Remove( elem );
  380. return true;
  381. }
  382. return false;
  383. }
  384. bool FindAndFastRemove( const T& src )
  385. {
  386. int elem = Find( src );
  387. if ( elem != -1 )
  388. {
  389. FastRemove( elem );
  390. return true;
  391. }
  392. return false;
  393. }
  394. struct Data_t
  395. {
  396. int m_Size;
  397. T m_Elements[];
  398. };
  399. Data_t *m_pData;
  400. private:
  401. void ShiftElementsLeft( int elem, int num = 1 )
  402. {
  403. int Size = Count();
  404. Assert( IsValidIndex(elem) || ( Size == 0 ) || ( num == 0 ));
  405. int numToMove = Size - elem - num;
  406. if ((numToMove > 0) && (num > 0))
  407. {
  408. V_memmove( &Element(elem), &Element(elem+num), numToMove * sizeof(T) );
  409. #ifdef _DEBUG
  410. V_memset( &Element(Size-num), 0xDD, num * sizeof(T) );
  411. #endif
  412. }
  413. }
  414. static Data_t *StaticData()
  415. {
  416. static Data_t staticData;
  417. Assert( staticData.m_Size == 0 );
  418. return &staticData;
  419. }
  420. };
  421. #pragma warning(pop)
  422. //-----------------------------------------------------------------------------
  423. // The CCopyableUtlVector class:
  424. // A array class that allows copy construction (so you can nest a CUtlVector inside of another one of our containers)
  425. // WARNING - this class lets you copy construct which can be an expensive operation if you don't carefully control when it happens
  426. // Only use this when nesting a CUtlVector() inside of another one of our container classes (i.e a CUtlMap)
  427. //-----------------------------------------------------------------------------
  428. template< class T >
  429. class CCopyableUtlVector : public CUtlVector< T, CUtlMemory<T> >
  430. {
  431. typedef CUtlVector< T, CUtlMemory<T> > BaseClass;
  432. public:
  433. CCopyableUtlVector( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {}
  434. CCopyableUtlVector( T* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {}
  435. virtual ~CCopyableUtlVector() {}
  436. CCopyableUtlVector( CCopyableUtlVector const& vec ) { CopyArray( vec.Base(), vec.Count() ); }
  437. };
  438. // TODO (Ilya): It seems like all the functions in CUtlVector are simple enough that they should be inlined.
  439. //-----------------------------------------------------------------------------
  440. // constructor, destructor
  441. //-----------------------------------------------------------------------------
  442. template< typename T, class A >
  443. inline CUtlVector<T, A>::CUtlVector( int growSize, int initSize ) :
  444. m_Memory(growSize, initSize), m_Size(0)
  445. {
  446. ResetDbgInfo();
  447. }
  448. template< typename T, class A >
  449. inline CUtlVector<T, A>::CUtlVector( T* pMemory, int allocationCount, int numElements ) :
  450. m_Memory(pMemory, allocationCount), m_Size(numElements)
  451. {
  452. ResetDbgInfo();
  453. }
  454. template< typename T, class A >
  455. inline CUtlVector<T, A>::~CUtlVector()
  456. {
  457. Purge();
  458. }
  459. template< typename T, class A >
  460. inline CUtlVector<T, A>& CUtlVector<T, A>::operator=( const CUtlVector<T, A> &other )
  461. {
  462. int nCount = other.Count();
  463. SetSize( nCount );
  464. for ( int i = 0; i < nCount; i++ )
  465. {
  466. (*this)[ i ] = other[ i ];
  467. }
  468. return *this;
  469. }
  470. //-----------------------------------------------------------------------------
  471. // element access
  472. //-----------------------------------------------------------------------------
  473. template< typename T, class A >
  474. inline T& CUtlVector<T, A>::operator[]( int i )
  475. {
  476. Assert( i < m_Size );
  477. return m_Memory[ i ];
  478. }
  479. template< typename T, class A >
  480. inline const T& CUtlVector<T, A>::operator[]( int i ) const
  481. {
  482. Assert( i < m_Size );
  483. return m_Memory[ i ];
  484. }
  485. template< typename T, class A >
  486. inline T& CUtlVector<T, A>::Element( int i )
  487. {
  488. Assert( i < m_Size );
  489. return m_Memory[ i ];
  490. }
  491. template< typename T, class A >
  492. inline const T& CUtlVector<T, A>::Element( int i ) const
  493. {
  494. Assert( i < m_Size );
  495. return m_Memory[ i ];
  496. }
  497. template< typename T, class A >
  498. inline T& CUtlVector<T, A>::Head()
  499. {
  500. Assert( m_Size > 0 );
  501. return m_Memory[ 0 ];
  502. }
  503. template< typename T, class A >
  504. inline const T& CUtlVector<T, A>::Head() const
  505. {
  506. Assert( m_Size > 0 );
  507. return m_Memory[ 0 ];
  508. }
  509. template< typename T, class A >
  510. inline T& CUtlVector<T, A>::Tail()
  511. {
  512. Assert( m_Size > 0 );
  513. return m_Memory[ m_Size - 1 ];
  514. }
  515. template< typename T, class A >
  516. inline const T& CUtlVector<T, A>::Tail() const
  517. {
  518. Assert( m_Size > 0 );
  519. return m_Memory[ m_Size - 1 ];
  520. }
  521. //-----------------------------------------------------------------------------
  522. // Count
  523. //-----------------------------------------------------------------------------
  524. template< typename T, class A >
  525. inline int CUtlVector<T, A>::Count() const
  526. {
  527. return m_Size;
  528. }
  529. //-----------------------------------------------------------------------------
  530. // Is element index valid?
  531. //-----------------------------------------------------------------------------
  532. template< typename T, class A >
  533. inline bool CUtlVector<T, A>::IsValidIndex( int i ) const
  534. {
  535. return (i >= 0) && (i < m_Size);
  536. }
  537. //-----------------------------------------------------------------------------
  538. // Returns in invalid index
  539. //-----------------------------------------------------------------------------
  540. template< typename T, class A >
  541. inline int CUtlVector<T, A>::InvalidIndex()
  542. {
  543. return -1;
  544. }
  545. //-----------------------------------------------------------------------------
  546. // Grows the vector
  547. //-----------------------------------------------------------------------------
  548. template< typename T, class A >
  549. void CUtlVector<T, A>::GrowVector( int num )
  550. {
  551. if (m_Size + num > m_Memory.NumAllocated())
  552. {
  553. MEM_ALLOC_CREDIT_CLASS();
  554. m_Memory.Grow( m_Size + num - m_Memory.NumAllocated() );
  555. }
  556. m_Size += num;
  557. ResetDbgInfo();
  558. }
  559. //-----------------------------------------------------------------------------
  560. // Sorts the vector
  561. //-----------------------------------------------------------------------------
  562. template< typename T, class A >
  563. void CUtlVector<T, A>::Sort( int (__cdecl *pfnCompare)(const T *, const T *) )
  564. {
  565. typedef int (__cdecl *QSortCompareFunc_t)(const void *, const void *);
  566. if ( Count() <= 1 )
  567. return;
  568. if ( Base() )
  569. {
  570. qsort( Base(), Count(), sizeof(T), (QSortCompareFunc_t)(pfnCompare) );
  571. }
  572. else
  573. {
  574. Assert( 0 );
  575. // this path is untested
  576. // if you want to sort vectors that use a non-sequential memory allocator,
  577. // you'll probably want to patch in a quicksort algorithm here
  578. // I just threw in this bubble sort to have something just in case...
  579. for ( int i = m_Size - 1; i >= 0; --i )
  580. {
  581. for ( int j = 1; j <= i; ++j )
  582. {
  583. if ( pfnCompare( &Element( j - 1 ), &Element( j ) ) < 0 )
  584. {
  585. V_swap( Element( j - 1 ), Element( j ) );
  586. }
  587. }
  588. }
  589. }
  590. }
  591. //----------------------------------------------------------------------------------------------
  592. // Private function that does the in-place quicksort for non-contiguously allocated vectors.
  593. //----------------------------------------------------------------------------------------------
  594. template< typename T, class A >
  595. void CUtlVector<T, A>::InPlaceQuickSort_r( int (__cdecl *pfnCompare)(const T *, const T *), int nLeft, int nRight )
  596. {
  597. int nPivot;
  598. int nLeftIdx = nLeft;
  599. int nRightIdx = nRight;
  600. if ( nRight - nLeft > 0 )
  601. {
  602. nPivot = ( nLeft + nRight ) / 2;
  603. while ( ( nLeftIdx <= nPivot ) && ( nRightIdx >= nPivot ) )
  604. {
  605. while ( ( pfnCompare( &Element( nLeftIdx ), &Element( nPivot ) ) < 0 ) && ( nLeftIdx <= nPivot ) )
  606. {
  607. nLeftIdx++;
  608. }
  609. while ( ( pfnCompare( &Element( nRightIdx ), &Element( nPivot ) ) > 0 ) && ( nRightIdx >= nPivot ) )
  610. {
  611. nRightIdx--;
  612. }
  613. V_swap( Element( nLeftIdx ), Element( nRightIdx ) );
  614. nLeftIdx++;
  615. nRightIdx--;
  616. if ( ( nLeftIdx - 1 ) == nPivot )
  617. {
  618. nPivot = nRightIdx = nRightIdx + 1;
  619. }
  620. else if ( nRightIdx + 1 == nPivot )
  621. {
  622. nPivot = nLeftIdx = nLeftIdx - 1;
  623. }
  624. }
  625. InPlaceQuickSort_r( pfnCompare, nLeft, nPivot - 1 );
  626. InPlaceQuickSort_r( pfnCompare, nPivot + 1, nRight );
  627. }
  628. }
  629. //----------------------------------------------------------------------------------------------
  630. // Call this to quickly sort non-contiguously allocated vectors. Sort uses a slower bubble sort.
  631. //----------------------------------------------------------------------------------------------
  632. template< typename T, class A >
  633. void CUtlVector<T, A>::InPlaceQuickSort( int (__cdecl *pfnCompare)(const T *, const T *) )
  634. {
  635. InPlaceQuickSort_r( pfnCompare, 0, Count() - 1 );
  636. }
  637. //-----------------------------------------------------------------------------
  638. // Makes sure we have enough memory allocated to store a requested # of elements
  639. //-----------------------------------------------------------------------------
  640. template< typename T, class A >
  641. void CUtlVector<T, A>::EnsureCapacity( int num )
  642. {
  643. MEM_ALLOC_CREDIT_CLASS();
  644. m_Memory.EnsureCapacity(num);
  645. ResetDbgInfo();
  646. }
  647. //-----------------------------------------------------------------------------
  648. // Makes sure we have at least this many elements
  649. //-----------------------------------------------------------------------------
  650. template< typename T, class A >
  651. void CUtlVector<T, A>::EnsureCount( int num )
  652. {
  653. if (Count() < num)
  654. {
  655. AddMultipleToTail( num - Count() );
  656. }
  657. }
  658. //-----------------------------------------------------------------------------
  659. // Shifts elements
  660. //-----------------------------------------------------------------------------
  661. template< typename T, class A >
  662. void CUtlVector<T, A>::ShiftElementsRight( int elem, int num )
  663. {
  664. Assert( IsValidIndex(elem) || ( m_Size == 0 ) || ( num == 0 ));
  665. int numToMove = m_Size - elem - num;
  666. if ((numToMove > 0) && (num > 0))
  667. V_memmove( &Element(elem+num), &Element(elem), numToMove * sizeof(T) );
  668. }
  669. template< typename T, class A >
  670. void CUtlVector<T, A>::ShiftElementsLeft( int elem, int num )
  671. {
  672. Assert( IsValidIndex(elem) || ( m_Size == 0 ) || ( num == 0 ));
  673. int numToMove = m_Size - elem - num;
  674. if ((numToMove > 0) && (num > 0))
  675. {
  676. V_memmove( &Element(elem), &Element(elem+num), numToMove * sizeof(T) );
  677. #ifdef _DEBUG
  678. V_memset( &Element(m_Size-num), 0xDD, num * sizeof(T) );
  679. #endif
  680. }
  681. }
  682. //-----------------------------------------------------------------------------
  683. // Adds an element, uses default constructor
  684. //-----------------------------------------------------------------------------
  685. template< typename T, class A >
  686. inline int CUtlVector<T, A>::AddToHead()
  687. {
  688. return InsertBefore(0);
  689. }
  690. template< typename T, class A >
  691. inline int CUtlVector<T, A>::AddToTail()
  692. {
  693. return InsertBefore( m_Size );
  694. }
  695. template< typename T, class A >
  696. inline int CUtlVector<T, A>::InsertAfter( int elem )
  697. {
  698. return InsertBefore( elem + 1 );
  699. }
  700. template< typename T, class A >
  701. int CUtlVector<T, A>::InsertBefore( int elem )
  702. {
  703. // Can insert at the end
  704. Assert( (elem == Count()) || IsValidIndex(elem) );
  705. GrowVector();
  706. ShiftElementsRight(elem);
  707. Construct( &Element(elem) );
  708. return elem;
  709. }
  710. //-----------------------------------------------------------------------------
  711. // Adds an element, uses copy constructor
  712. //-----------------------------------------------------------------------------
  713. template< typename T, class A >
  714. inline int CUtlVector<T, A>::AddToHead( const T& src )
  715. {
  716. // Can't insert something that's in the list... reallocation may hose us
  717. Assert( (Base() == NULL) || (&src < Base()) || (&src >= (Base() + Count()) ) );
  718. return InsertBefore( 0, src );
  719. }
  720. template< typename T, class A >
  721. inline int CUtlVector<T, A>::AddToTail( const T& src )
  722. {
  723. // Can't insert something that's in the list... reallocation may hose us
  724. Assert( (Base() == NULL) || (&src < Base()) || (&src >= (Base() + Count()) ) );
  725. return InsertBefore( m_Size, src );
  726. }
  727. template< typename T, class A >
  728. inline int CUtlVector<T, A>::InsertAfter( int elem, const T& src )
  729. {
  730. // Can't insert something that's in the list... reallocation may hose us
  731. Assert( (Base() == NULL) || (&src < Base()) || (&src >= (Base() + Count()) ) );
  732. return InsertBefore( elem + 1, src );
  733. }
  734. template< typename T, class A >
  735. int CUtlVector<T, A>::InsertBefore( int elem, const T& src )
  736. {
  737. // Can't insert something that's in the list... reallocation may hose us
  738. Assert( (Base() == NULL) || (&src < Base()) || (&src >= (Base() + Count()) ) );
  739. // Can insert at the end
  740. Assert( (elem == Count()) || IsValidIndex(elem) );
  741. GrowVector();
  742. ShiftElementsRight(elem);
  743. CopyConstruct( &Element(elem), src );
  744. return elem;
  745. }
  746. //-----------------------------------------------------------------------------
  747. // Adds multiple elements, uses default constructor
  748. //-----------------------------------------------------------------------------
  749. template< typename T, class A >
  750. inline int CUtlVector<T, A>::AddMultipleToHead( int num )
  751. {
  752. return InsertMultipleBefore( 0, num );
  753. }
  754. template< typename T, class A >
  755. inline int CUtlVector<T, A>::AddMultipleToTail( int num )
  756. {
  757. return InsertMultipleBefore( m_Size, num );
  758. }
  759. template< typename T, class A >
  760. inline int CUtlVector<T, A>::AddMultipleToTail( int num, const T *pToCopy )
  761. {
  762. // Can't insert something that's in the list... reallocation may hose us
  763. Assert( (Base() == NULL) || !pToCopy || (pToCopy + num <= Base()) || (pToCopy >= (Base() + Count()) ) );
  764. return InsertMultipleBefore( m_Size, num, pToCopy );
  765. }
  766. template< typename T, class A >
  767. int CUtlVector<T, A>::InsertMultipleAfter( int elem, int num )
  768. {
  769. return InsertMultipleBefore( elem + 1, num );
  770. }
  771. template< typename T, class A >
  772. void CUtlVector<T, A>::SetCount( int count )
  773. {
  774. RemoveAll();
  775. AddMultipleToTail( count );
  776. }
  777. template< typename T, class A >
  778. inline void CUtlVector<T, A>::SetSize( int size )
  779. {
  780. SetCount( size );
  781. }
  782. template< typename T, class A >
  783. void CUtlVector<T, A>::SetCountNonDestructively( int count )
  784. {
  785. int delta = count - m_Size;
  786. if(delta > 0) AddMultipleToTail( delta );
  787. else if(delta < 0) RemoveMultipleFromTail( -delta );
  788. }
  789. template< typename T, class A >
  790. void CUtlVector<T, A>::CopyArray( const T *pArray, int size )
  791. {
  792. // Can't insert something that's in the list... reallocation may hose us
  793. Assert( (Base() == NULL) || !pArray || (Base() >= (pArray + size)) || (pArray >= (Base() + Count()) ) );
  794. SetSize( size );
  795. for( int i=0; i < size; i++ )
  796. {
  797. (*this)[i] = pArray[i];
  798. }
  799. }
  800. template< typename T, class A >
  801. void CUtlVector<T, A>::Swap( CUtlVector< T, A > &vec )
  802. {
  803. m_Memory.Swap( vec.m_Memory );
  804. V_swap( m_Size, vec.m_Size );
  805. #ifndef _X360
  806. V_swap( m_pElements, vec.m_pElements );
  807. #endif
  808. }
  809. template< typename T, class A >
  810. int CUtlVector<T, A>::AddVectorToTail( CUtlVector const &src )
  811. {
  812. Assert( &src != this );
  813. int base = Count();
  814. // Make space.
  815. int nSrcCount = src.Count();
  816. EnsureCapacity( base + nSrcCount );
  817. // Copy the elements.
  818. m_Size += nSrcCount;
  819. for ( int i=0; i < nSrcCount; i++ )
  820. {
  821. CopyConstruct( &Element(base+i), src[i] );
  822. }
  823. return base;
  824. }
  825. template< typename T, class A >
  826. inline int CUtlVector<T, A>::InsertMultipleBefore( int elem, int num )
  827. {
  828. if( num == 0 )
  829. return elem;
  830. // Can insert at the end
  831. Assert( (elem == Count()) || IsValidIndex(elem) );
  832. GrowVector(num);
  833. ShiftElementsRight( elem, num );
  834. // Invoke default constructors
  835. for (int i = 0; i < num; ++i )
  836. {
  837. Construct( &Element( elem+i ) );
  838. }
  839. return elem;
  840. }
  841. template< typename T, class A >
  842. inline int CUtlVector<T, A>::InsertMultipleBefore( int elem, int num, const T *pToInsert )
  843. {
  844. if( num == 0 )
  845. return elem;
  846. // Can insert at the end
  847. Assert( (elem == Count()) || IsValidIndex(elem) );
  848. GrowVector(num);
  849. ShiftElementsRight( elem, num );
  850. // Invoke default constructors
  851. if ( !pToInsert )
  852. {
  853. for (int i = 0; i < num; ++i )
  854. {
  855. Construct( &Element( elem+i ) );
  856. }
  857. }
  858. else
  859. {
  860. for ( int i=0; i < num; i++ )
  861. {
  862. CopyConstruct( &Element( elem+i ), pToInsert[i] );
  863. }
  864. }
  865. return elem;
  866. }
  867. //-----------------------------------------------------------------------------
  868. // Finds an element (element needs operator== defined)
  869. //-----------------------------------------------------------------------------
  870. template< typename T, class A >
  871. int CUtlVector<T, A>::Find( const T& src ) const
  872. {
  873. for ( int i = 0; i < Count(); ++i )
  874. {
  875. if (Element(i) == src)
  876. return i;
  877. }
  878. return -1;
  879. }
  880. template< typename T, class A >
  881. void CUtlVector<T, A>::FillWithValue( const T& src )
  882. {
  883. for ( int i = 0; i < Count(); i++ )
  884. {
  885. Element(i) = src;
  886. }
  887. }
  888. template< typename T, class A >
  889. bool CUtlVector<T, A>::HasElement( const T& src ) const
  890. {
  891. return ( Find(src) >= 0 );
  892. }
  893. //-----------------------------------------------------------------------------
  894. // Element removal
  895. //-----------------------------------------------------------------------------
  896. template< typename T, class A >
  897. void CUtlVector<T, A>::FastRemove( int elem )
  898. {
  899. Assert( IsValidIndex(elem) );
  900. Destruct( &Element(elem) );
  901. if (m_Size > 0)
  902. {
  903. if ( elem != m_Size -1 )
  904. memcpy( &Element(elem), &Element(m_Size-1), sizeof(T) );
  905. --m_Size;
  906. }
  907. }
  908. template< typename T, class A >
  909. void CUtlVector<T, A>::Remove( int elem )
  910. {
  911. Destruct( &Element(elem) );
  912. ShiftElementsLeft(elem);
  913. --m_Size;
  914. }
  915. template< typename T, class A >
  916. bool CUtlVector<T, A>::FindAndRemove( const T& src )
  917. {
  918. int elem = Find( src );
  919. if ( elem != -1 )
  920. {
  921. Remove( elem );
  922. return true;
  923. }
  924. return false;
  925. }
  926. template< typename T, class A >
  927. bool CUtlVector<T, A>::FindAndFastRemove( const T& src )
  928. {
  929. int elem = Find( src );
  930. if ( elem != -1 )
  931. {
  932. FastRemove( elem );
  933. return true;
  934. }
  935. return false;
  936. }
  937. template< typename T, class A >
  938. void CUtlVector<T, A>::RemoveMultiple( int elem, int num )
  939. {
  940. Assert( elem >= 0 );
  941. Assert( elem + num <= Count() );
  942. for (int i = elem + num; --i >= elem; )
  943. Destruct(&Element(i));
  944. ShiftElementsLeft(elem, num);
  945. m_Size -= num;
  946. }
  947. template< typename T, class A >
  948. void CUtlVector<T, A>::RemoveMultipleFromHead( int num )
  949. {
  950. Assert( num <= Count() );
  951. for (int i = num; --i >= 0; )
  952. Destruct(&Element(i));
  953. ShiftElementsLeft(0, num);
  954. m_Size -= num;
  955. }
  956. template< typename T, class A >
  957. void CUtlVector<T, A>::RemoveMultipleFromTail( int num )
  958. {
  959. Assert( num <= Count() );
  960. for (int i = m_Size-num; i < m_Size; i++)
  961. Destruct(&Element(i));
  962. m_Size -= num;
  963. }
  964. template< typename T, class A >
  965. void CUtlVector<T, A>::RemoveAll()
  966. {
  967. for (int i = m_Size; --i >= 0; )
  968. {
  969. Destruct(&Element(i));
  970. }
  971. m_Size = 0;
  972. }
  973. //-----------------------------------------------------------------------------
  974. // Memory deallocation
  975. //-----------------------------------------------------------------------------
  976. template< typename T, class A >
  977. inline void CUtlVector<T, A>::Purge()
  978. {
  979. RemoveAll();
  980. m_Memory.Purge();
  981. ResetDbgInfo();
  982. }
  983. template< typename T, class A >
  984. inline void CUtlVector<T, A>::PurgeAndDeleteElements()
  985. {
  986. for( int i=0; i < m_Size; i++ )
  987. {
  988. delete Element(i);
  989. }
  990. Purge();
  991. }
  992. template< typename T, class A >
  993. inline void CUtlVector<T, A>::Compact()
  994. {
  995. m_Memory.Purge(m_Size);
  996. }
  997. template< typename T, class A >
  998. inline int CUtlVector<T, A>::NumAllocated() const
  999. {
  1000. return m_Memory.NumAllocated();
  1001. }
  1002. //-----------------------------------------------------------------------------
  1003. // Data and memory validation
  1004. //-----------------------------------------------------------------------------
  1005. #ifdef DBGFLAG_VALIDATE
  1006. template< typename T, class A >
  1007. void CUtlVector<T, A>::Validate( CValidator &validator, char *pchName )
  1008. {
  1009. validator.Push( typeid(*this).name(), this, pchName );
  1010. m_Memory.Validate( validator, "m_Memory" );
  1011. validator.Pop();
  1012. }
  1013. #endif // DBGFLAG_VALIDATE
  1014. // A vector class for storing pointers, so that the elements pointed to by the pointers are deleted
  1015. // on exit.
  1016. template<class T> class CUtlVectorAutoPurge : public CUtlVector< T, CUtlMemory< T, int> >
  1017. {
  1018. public:
  1019. ~CUtlVectorAutoPurge( void )
  1020. {
  1021. this->PurgeAndDeleteElements();
  1022. }
  1023. };
  1024. // easy string list class with dynamically allocated strings. For use with V_SplitString, etc.
  1025. // Frees the dynamic strings in destructor.
  1026. class CUtlStringList : public CUtlVectorAutoPurge< char *>
  1027. {
  1028. public:
  1029. void CopyAndAddToTail( char const *pString ) // clone the string and add to the end
  1030. {
  1031. char *pNewStr = new char[1 + strlen( pString )];
  1032. V_strcpy( pNewStr, pString );
  1033. AddToTail( pNewStr );
  1034. }
  1035. static int __cdecl SortFunc( char * const * sz1, char * const * sz2 )
  1036. {
  1037. return strcmp( *sz1, *sz2 );
  1038. }
  1039. };
  1040. // <Sergiy> placing it here a few days before Cert to minimize disruption to the rest of codebase
  1041. class CSplitString: public CUtlVector<char*, CUtlMemory<char*, int> >
  1042. {
  1043. public:
  1044. CSplitString(const char *pString, const char *pSeparator);
  1045. CSplitString(const char *pString, const char **pSeparators, int nSeparators);
  1046. ~CSplitString();
  1047. //
  1048. // NOTE: If you want to make Construct() public and implement Purge() here, you'll have to free m_szBuffer there
  1049. //
  1050. private:
  1051. void Construct(const char *pString, const char **pSeparators, int nSeparators);
  1052. void PurgeAndDeleteElements();
  1053. private:
  1054. char *m_szBuffer; // a copy of original string, with '\0' instead of separators
  1055. };
  1056. #endif // CCVECTOR_H