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.

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