#ifndef UTLVECTOR_H
#define UTLVECTOR_H
#ifdef _WIN32
#pragma once
#endif
#include <string.h>
#include "tier0/memdbgoff.h"
#include <algorithm>
#include <functional>
#include <type_traits>
#include "tier0/memdbgon.h"
#include "tier0/platform.h"
#include "tier0/dbg.h"
#include "tier1/utlmemory.h"
#include "vstdlib/strtools.h"
#define FOR_EACH_VEC( vecName, iteratorName ) \
for ( int iteratorName = 0; iteratorName < (vecName).Count(); iteratorName++ )
#define FOR_EACH_VEC_BACK( vecName, iteratorName ) \
for ( int iteratorName = (vecName).Count()-1; iteratorName >= 0; iteratorName-- )
BEGIN_TIER1_NAMESPACE
template< class T, class A = CUtlMemory<T> >
class CUtlVector
{
typedef A CAllocator;
public:
typedef T ElemType_t;
typedef T* iterator;
typedef const T* const_iterator;
explicit CUtlVector( int growSize = 0, int initSize = 0 );
#ifdef VALVE_RVALUE_REFS
CUtlVector( CUtlVector&& src );
#endif CUtlVector( T* pMemory, int allocationCount, int numElements = 0 );
#ifdef VALVE_INITIALIZER_LIST_SUPPORT
CUtlVector( std::initializer_list<T> initializerList );
#endif ~CUtlVector();
CUtlVector<T, A>& operator=( const CUtlVector<T, A> &other );
T& operator[]( int i );
const T& operator[]( int i ) const;
T& Element( int i );
const T& Element( int i ) const;
T& Head();
const T& Head() const;
T& Tail();
const T& Tail() const;
iterator begin() { return Base(); }
const_iterator begin() const { return Base(); }
iterator end() { return Base() + Count(); }
const_iterator end() const { return Base() + Count(); }
T* Base() { return m_Memory.Base(); }
const T* Base() const { return m_Memory.Base(); }
int Count() const;
bool IsEmpty() const { return (Count() == 0); }
int CubAllocated() { return m_Memory.CubAllocated(); }
bool IsValidIndex( int i ) const;
static int InvalidIndex();
int AddToHead();
int AddToTail();
T *AddToTailGetPtr();
int InsertBefore( int elem );
int InsertAfter( int elem );
int AddToHead( const T& src );
int AddToTail( const T& src );
int InsertBefore( int elem, const T& src );
int InsertAfter( int elem, const T& src );
#ifdef VALVE_RVALUE_REFS
int AddToTail( T&& src );
#endif
int AddMultipleToHead( int num );
int AddMultipleToTail( int num, const T *pToCopy=NULL );
int InsertMultipleBefore( int elem, int num, const T *pToCopy=NULL ); int InsertMultipleAfter( int elem, int num, const T *pToCopy=NULL );
void SetCount( int count );
void CopyArray( const T *pArray, int size );
void Swap( CUtlVector< T, A > &vec );
int AddVectorToTail( CUtlVector<T, A> const &src );
int Find( const T& src ) const;
#ifdef VALVE_RVALUE_REFS
template < typename TMatchFunc >
int FindMatch( TMatchFunc&& func ) const;
#endif
bool HasElement( const T& src ) const;
void EnsureCapacity( int num );
void EnsureCount( int num );
void FastRemove( int elem ); void Remove( int elem ); bool FindAndRemove( const T& src ); bool FindAndFastRemove( const T& src ); void RemoveMultiple( int elem, int num ); void RemoveMultipleFromTail( int num );
void RemoveAll();
void Purge();
void PurgeAndDeleteElements();
void Compact();
void SetGrowSize( int size ) { m_Memory.SetGrowSize( size ); }
int NumAllocated() const { return m_Memory.NumAllocated(); }
void Reverse();
int SortedFind( const T& search, bool (__cdecl *pfnLessFunc)( const T& src1, const T& src2, void *pCtx ), void *pLessContext ) const;
int SortedFind( const T& search, bool (__cdecl *pfnLessFunc)( const T& src1, const T& src2 ) ) const;
int SortedFindFirst( const T& search, bool (__cdecl *pfnLessFunc)( const T& src1, const T& src2, void *pCtx ), void *pLessContext ) const;
int SortedFindLessOrEqual( const T& search, bool (__cdecl *pfnLessFunc)( const T& src1, const T& src2, void *pCtx ), void *pLessContext, int start, int end ) const;
int SortedFindLessOrEqual( const T& search, bool (__cdecl *pfnLessFunc)( const T& src1, const T& src2, void *pCtx ), void *pLessContext ) const;
int SortedFindLessOrEqual( const T& search, bool (__cdecl *pfnLessFunc)( const T& src1, const T& src2 ), int start, int end ) const;
int SortedFindLessOrEqual( const T& search, bool (__cdecl *pfnLessFunc)( const T& src1, const T& src2 ) ) const;
template <typename T2>
int SortedFindIf( const T2 &comparerPredicate ) const;
template <typename T2>
int SortedFindFirst( const T2 &comparerPredicate ) const;
template <typename T2>
const T& FindElementIf( const T2 &comparerPredicate, const T& defaultParam ) const;
int SortedInsert( const T& src, bool (__cdecl *pfnLessFunc)( const T& src1, const T& src2, void *pCtx ), void *pLessContext );
int SortedInsert( const T& src, bool (__cdecl *pfnLessFunc)( const T& src1, const T& src2 ) );
template <class F> void SortPredicate( F &&predicate );
void Sort() { SortPredicate( std::less<T>{} ); };
void Sort( int (__cdecl *pfnCompare)(const T *, const T *) );
void Sort_s( void *context, int (__cdecl *pfnCompare)(void *, const T *, const T *) );
void Sort( bool( __cdecl *pfnLessFunc )(const T& src1, const T& src2) );
void Sort( bool( __cdecl *pfnLessFunc )(const T& src1, const T& src2, void *pCtx), void *pLessContext );
void Sort_s( void *context, bool (__cdecl *pfnLessFunc)( const T& src1, const T& src2, void *pCtx ) );
#ifdef DBGFLAG_VALIDATE
void Validate( CValidator &validator, const char *pchName ); void ValidateSelfAndElements( CValidator &validator, const char *pchName ); #endif
protected:
CUtlVector( CUtlVector const& );
void GrowVector( int num = 1 );
void ShiftElementsRight( int elem, int num = 1 );
void ShiftElementsLeft( int elem, int num = 1 );
CAllocator m_Memory;
int m_Size;
};
template< class T, size_t MAX_SIZE >
class CUtlVectorFixed : public CUtlVector< T, CUtlMemoryFixed<T, MAX_SIZE > >
{
typedef CUtlVector< T, CUtlMemoryFixed<T, MAX_SIZE > > BaseClass;
public:
CUtlVectorFixed( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {}
CUtlVectorFixed( T* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {}
};
template< class T, size_t MAX_SIZE >
class CCopyableUtlVectorFixed : public CUtlVectorFixed< T, MAX_SIZE >
{
typedef CUtlVectorFixed< T, MAX_SIZE > BaseClass;
public:
CCopyableUtlVectorFixed( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {}
CCopyableUtlVectorFixed( T* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {}
CCopyableUtlVectorFixed( CCopyableUtlVectorFixed const& vec ) : BaseClass(0,0) { this->CopyArray( vec.Base(), vec.Count() ); }
};
template< class T, class A = CUtlMemory<T> >
class CCopyableUtlVector : public CUtlVector< T, A >
{
typedef CUtlVector< T, A > BaseClass;
public:
CCopyableUtlVector( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {}
CCopyableUtlVector( T* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {}
CCopyableUtlVector( CCopyableUtlVector const& vec ) : BaseClass(0,0) { this->CopyArray( vec.Base(), vec.Count() ); }
CCopyableUtlVector( CUtlVector<T,A> const& vec ) : BaseClass( 0, 0 ) { this->CopyArray( vec.Base(), vec.Count() ); }
};
template< typename T, class A >
inline CUtlVector<T, A>::CUtlVector( int growSize, int initSize ) :
m_Memory(growSize, initSize), m_Size(0)
{
}
#ifdef VALVE_RVALUE_REFS
template< typename T, class A >
inline CUtlVector<T, A>::CUtlVector( CUtlVector<T, A>&& src )
: m_Size( 0 )
{
Swap( src );
}
#endif
template< typename T, class A >
inline CUtlVector<T, A>::CUtlVector( T* pMemory, int allocationCount, int numElements ) :
m_Memory(pMemory, allocationCount), m_Size(numElements)
{
}
#ifdef VALVE_INITIALIZER_LIST_SUPPORT
template< typename T, class A >
inline CUtlVector<T, A>::CUtlVector( std::initializer_list<T> initializerList ) :
m_Size(0)
{
EnsureCapacity( static_cast<int>( initializerList.size() ) );
for ( const auto& v : initializerList )
AddToTail( v );
}
#endif
template< typename T, class A >
inline CUtlVector<T, A>::~CUtlVector()
{
Purge();
}
template< typename T, class A >
inline CUtlVector<T, A>& CUtlVector<T, A>::operator=( const CUtlVector<T, A> &other )
{
this->CopyArray( other.Base(), other.Count() );
return *this;
}
template< typename T, class A >
inline T& CUtlVector<T, A>::operator[]( int i )
{
DbgAssert( IsValidIndex(i) );
return Base()[i];
}
template< typename T, class A >
inline const T& CUtlVector<T, A>::operator[]( int i ) const
{
DbgAssert( IsValidIndex(i) );
return Base()[i];
}
template< typename T, class A >
inline T& CUtlVector<T, A>::Element( int i )
{
DbgAssert( IsValidIndex(i) );
return Base()[i];
}
template< typename T, class A >
inline const T& CUtlVector<T, A>::Element( int i ) const
{
DbgAssert( IsValidIndex(i) );
return Base()[i];
}
template< typename T, class A >
inline T& CUtlVector<T, A>::Head()
{
DbgAssert( m_Size > 0 );
return m_Memory[0];
}
template< typename T, class A >
inline const T& CUtlVector<T, A>::Head() const
{
DbgAssert( m_Size > 0 );
return m_Memory[0];
}
template< typename T, class A >
inline T& CUtlVector<T, A>::Tail()
{
DbgAssert( m_Size > 0 );
return m_Memory[m_Size - 1];
}
template< typename T, class A >
inline const T& CUtlVector<T, A>::Tail() const
{
DbgAssert( m_Size > 0 );
return m_Memory[m_Size - 1];
}
template< typename T, class A >
inline int CUtlVector<T, A>::Count() const
{
return m_Size;
}
template< typename T, class A >
inline bool CUtlVector<T, A>::IsValidIndex( int i ) const
{
return (i >= 0) && (i < m_Size);
}
template< typename T, class A >
inline int CUtlVector<T, A>::InvalidIndex()
{
return -1;
}
template< typename T, class A >
inline void CUtlVector<T, A>::GrowVector( int num )
{
if (m_Size + num > m_Memory.NumAllocated())
{
m_Memory.Grow( m_Size + num - m_Memory.NumAllocated() );
}
m_Size += num;
}
template< typename T, class A >
inline void CUtlVector<T, A>::Reverse()
{
T* pBase = Base();
int iRight = m_Size - 1;
for( int iLeft = 0; iLeft < m_Size / 2; iLeft++ )
{
SWAP( pBase[iLeft], pBase[iRight] );
iRight--;
}
}
template< typename T, class A >
inline int CUtlVector<T, A>::SortedFind( const T& search, bool (__cdecl *pfnLessFunc)( const T& src1, const T& src2, void *pCtx ), void *pLessContext ) const
{
int start = 0, stop = Count() - 1;
while (start <= stop)
{
int mid = (start + stop) >> 1;
if ( pfnLessFunc( Base()[mid], search, pLessContext ) )
{
start = mid + 1;
}
else if ( pfnLessFunc( search, Base()[mid], pLessContext ) )
{
stop = mid - 1;
}
else
{
return mid;
}
}
return InvalidIndex();
}
template< typename T, class A >
inline int CUtlVector<T, A>::SortedFind( const T& search, bool (__cdecl *pfnLessFunc)( const T& src1, const T& src2 ) ) const
{
int start = 0, stop = Count() - 1;
while (start <= stop)
{
int mid = (start + stop) >> 1;
if ( pfnLessFunc( Base()[mid], search ) )
{
start = mid + 1;
}
else if ( pfnLessFunc( search, Base()[mid] ) )
{
stop = mid - 1;
}
else
{
return mid;
}
}
return InvalidIndex();
}
template< typename T, class A >
inline int CUtlVector<T, A>::SortedFindFirst( const T& search, bool (__cdecl *pfnLessFunc)( const T& src1, const T& src2, void *pCtx ), void *pLessContext ) const
{
int start = 0, stop = Count() - 1;
while (start <= stop)
{
int mid = (start + stop) >> 1;
if ( pfnLessFunc( Base()[mid], search, pLessContext ) )
{
start = mid + 1;
}
else if ( pfnLessFunc( search, Base()[mid], pLessContext ) )
{
stop = mid - 1;
}
else
{
if ( start == mid )
return mid;
stop = mid;
}
}
return InvalidIndex();
}
template< typename T, class A >
inline int CUtlVector<T, A>::SortedFindLessOrEqual( const T& search, bool (__cdecl *pfnLessFunc)( const T& src1, const T& src2, void *pCtx ), void *pLessContext, int start, int stop ) const
{
while (start <= stop)
{
int mid = (start + stop) >> 1;
if ( pfnLessFunc( Base()[mid], search, pLessContext ) )
{
start = mid + 1;
}
else if ( pfnLessFunc( search, Base()[mid], pLessContext ) )
{
stop = mid - 1;
}
else
{
if( stop == mid )
return mid;
if( mid == start )
{
if( stop > mid && pfnLessFunc( search, Base()[mid + 1], pLessContext ) )
return mid;
else
return mid + 1;
}
else
{
start = mid;
}
}
}
return stop;
}
template< typename T, class A >
inline int CUtlVector<T, A>::SortedFindLessOrEqual( const T& search, bool (__cdecl *pfnLessFunc)( const T& src1, const T& src2, void *pCtx ), void *pLessContext ) const
{
return SortedFindLessOrEqual( search, pfnLessFunc, pLessContext, 0, Count() - 1 );
}
template< typename T, class A >
inline int CUtlVector<T, A>::SortedInsert( const T& src, bool (__cdecl *pfnLessFunc)( const T& src1, const T& src2, void *pCtx ), void *pLessContext )
{
int pos = SortedFindLessOrEqual( src, pfnLessFunc, pLessContext ) + 1;
GrowVector();
ShiftElementsRight(pos);
Construct<T>( &Element(pos), src );
return pos;
}
template< typename T, class A >
template <class F>
inline void CUtlVector<T, A>::SortPredicate( F &&predicate )
{
std::sort( begin(), end(), predicate );
}
template< typename T, class A >
inline int CUtlVector<T, A>::SortedFindLessOrEqual( const T& search, bool (__cdecl *pfnLessFunc)( const T& src1, const T& src2 ), int start, int stop ) const
{
while (start <= stop)
{
int mid = (start + stop) >> 1;
if ( pfnLessFunc( Base()[mid], search ) )
{
start = mid + 1;
}
else if ( pfnLessFunc( search, Base()[mid] ) )
{
stop = mid - 1;
}
else
{
if( stop == mid )
return mid;
if( mid == start )
{
if( stop > mid && pfnLessFunc( search, Base()[mid + 1] ) )
return mid;
else
return mid + 1;
}
else
{
start = mid;
}
}
}
return stop;
}
template< typename T, class A >
inline int CUtlVector<T, A>::SortedFindLessOrEqual( const T& search, bool (__cdecl *pfnLessFunc)( const T& src1, const T& src2 ) ) const
{
return SortedFindLessOrEqual( search, pfnLessFunc, 0, Count() - 1 );
}
template< typename T, class A >
template <typename T2>
inline int CUtlVector<T, A>::SortedFindFirst( const T2 &comparerPredicate ) const
{
int start = 0, stop = Count() - 1;
while ( start <= stop )
{
int mid = ( start + stop ) >> 1;
int nResult = comparerPredicate.Compare( Base()[mid] );
if ( nResult < 0 )
{
start = mid + 1;
}
else if ( nResult > 0 )
{
stop = mid - 1;
}
else
{
if ( start == mid )
return mid;
stop = mid;
}
}
return InvalidIndex();
}
template< typename T, class A >
template <typename T2>
inline int CUtlVector<T, A>::SortedFindIf( const T2 &comparerPredicate ) const
{
int start = 0, stop = Count() - 1;
while (start <= stop)
{
int mid = (start + stop) >> 1;
int nResult = comparerPredicate.Compare( Base()[mid] );
if ( nResult < 0 )
{
start = mid + 1;
}
else if ( nResult > 0 )
{
stop = mid - 1;
}
else
{
return mid;
}
}
return InvalidIndex();
}
template< typename T, class A >
template <typename T2>
inline const T& CUtlVector<T, A>::FindElementIf( const T2 &comparerPredicate, const T& defaultParam ) const
{
FOR_EACH_VEC(*this, index)
{
if ( comparerPredicate( Base()[index] ) )
{
return Base()[index];
}
}
return defaultParam;
}
template< typename T, class A >
inline int CUtlVector<T, A>::SortedInsert( const T& src, bool (__cdecl *pfnLessFunc)( const T& src1, const T& src2 ) )
{
int pos = SortedFindLessOrEqual( src, pfnLessFunc ) + 1;
GrowVector();
ShiftElementsRight(pos);
Construct<T>( &Element(pos), src );
return pos;
}
template< typename T, class A >
inline void CUtlVector<T, A>::Sort( int (__cdecl *pfnCompare)(const T *, const T *) )
{
std::sort( begin(), end(),
[pfnCompare] ( const T& a, const T& b ) -> bool
{
if ( &a == &b )
return false;
#ifdef DEBUG
const auto A_Cmp_B = (*pfnCompare)( &a, &b );
const auto B_Cmp_A = (*pfnCompare)( &b, &a );
if ( A_Cmp_B == 0 )
{
Assert( A_Cmp_B == B_Cmp_A );
}
else
{
Assert( (A_Cmp_B > 0) == (B_Cmp_A < 0) );
}
#endif
return (*pfnCompare)( &a, &b ) < 0;
} );
}
template< typename T, class A >
inline void CUtlVector<T, A>::Sort( bool (__cdecl *pfnLessFunc)( const T& src1, const T& src2 ) )
{
std::sort( begin(), end(),
[pfnLessFunc] ( const T& a, const T& b ) -> bool
{
if ( &a == &b )
return false;
#ifdef DEBUG
const auto A_Less_B = (*pfnLessFunc)( a, b );
const auto B_Less_A = (*pfnLessFunc)( b, a );
Assert( !A_Less_B || !B_Less_A );
#endif
return (*pfnLessFunc)( a, b );
} );
}
template< typename T, class A >
inline void CUtlVector<T, A>::Sort( bool( __cdecl *pfnLessFunc )(const T& src1, const T& src2, void *pCtx), void *pLessContext )
{
std::sort( begin(), end(),
[pfnLessFunc, pLessContext] ( const T& a, const T& b ) -> bool
{
if ( &a == &b )
return false;
#ifdef DEBUG
const auto A_Less_B = (*pfnLessFunc)( a, b, pLessContext);
const auto B_Less_A = (*pfnLessFunc)( b, a, pLessContext );
Assert( !A_Less_B || !B_Less_A );
#endif
return (*pfnLessFunc)( a, b, pLessContext);
} );
}
template< typename T, class A >
inline void CUtlVector<T, A>::Sort_s( void *context, int (__cdecl *pfnCompare)(void *,const T *, const T *) )
{
std::sort( begin(), end(),
[context, pfnCompare] ( const T& a, const T& b ) -> bool
{
if ( &a == &b )
return false;
#ifdef DEBUG
const auto A_Cmp_B = (*pfnCompare)( context, &a, &b );
const auto B_Cmp_A = (*pfnCompare)( context, &b, &a );
if ( A_Cmp_B == 0 )
{
Assert( A_Cmp_B == B_Cmp_A );
}
else
{
Assert( (A_Cmp_B > 0) == (B_Cmp_A < 0) );
}
#endif
return (*pfnCompare)( context, &a, &b ) < 0;
} );
}
template< typename T, class A >
inline void CUtlVector<T, A>::Sort_s( void *context, bool (__cdecl *pfnLessFunc)( const T& src1, const T& src2, void *pCtx ) )
{
std::sort( begin(), end(),
[context, pfnLessFunc] ( const T& a, const T& b ) -> bool
{
if ( &a == &b )
return false;
#ifdef DEBUG
const auto A_Less_B = (*pfnLessFunc)( a, b, context );
const auto B_Less_A = (*pfnLessFunc)( b, a, context );
Assert( !A_Less_B || !B_Less_A );
#endif
return (*pfnLessFunc)( a, b, context );
} );
}
template< typename T, class A >
inline void CUtlVector<T, A>::EnsureCapacity( int num )
{
m_Memory.EnsureCapacity(num);
}
template< typename T, class A >
inline void CUtlVector<T, A>::EnsureCount( int num )
{
if (Count() < num)
AddMultipleToTail( num - Count() );
}
template< typename T, class A >
inline void CUtlVector<T, A>::ShiftElementsRight( int elem, int num )
{
DbgAssert( IsValidIndex(elem) || ( m_Size == 0 ) || ( num == 0 ));
int numToMove = m_Size - elem - num;
if ((numToMove > 0) && (num > 0))
memmove( (void*)&Element(elem+num), (void *)&Element(elem), numToMove * sizeof(T) );
}
template< typename T, class A >
inline void CUtlVector<T, A>::ShiftElementsLeft( int elem, int num )
{
DbgAssert( IsValidIndex(elem) || ( m_Size == 0 ) || ( num == 0 ));
int numToMove = m_Size - elem - num;
if ((numToMove > 0) && (num > 0))
{
memmove( (void*)&Element(elem), (void*)&Element(elem+num), numToMove * sizeof(T) );
#ifdef _DEBUG
memset( (void*)&Element(m_Size-num), 0xDD, num * sizeof(T) );
#endif
}
}
template< typename T, class A >
inline int CUtlVector<T, A>::AddToHead()
{
return InsertBefore(0);
}
template< typename T, class A >
inline int CUtlVector<T, A>::AddToTail()
{
return InsertBefore( m_Size );
}
template< typename T, class A >
inline T *CUtlVector<T, A>::AddToTailGetPtr()
{
return &Element( AddToTail() );
}
template< typename T, class A >
inline int CUtlVector<T, A>::InsertAfter( int elem )
{
return InsertBefore( elem + 1 );
}
template< typename T, class A >
inline int CUtlVector<T, A>::InsertBefore( int elem )
{
Assert( (elem == Count()) || IsValidIndex(elem) );
GrowVector();
ShiftElementsRight(elem);
Construct( &Element(elem) );
return elem;
}
template< typename T, class A >
inline int CUtlVector<T, A>::AddToHead( const T& src )
{
return InsertBefore( 0, src );
}
template< typename T, class A >
inline int CUtlVector<T, A>::AddToTail( const T& src )
{
return InsertBefore( m_Size, src );
}
template< typename T, class A >
inline int CUtlVector<T, A>::InsertAfter( int elem, const T& src )
{
return InsertBefore( elem + 1, src );
}
template< typename T, class A >
inline int CUtlVector<T, A>::InsertBefore( int elem, const T& src )
{
Assert( (&src < Base()) || (&src >= (Base() + Count()) ) );
Assert( (elem == Count()) || IsValidIndex(elem) );
GrowVector();
ShiftElementsRight(elem);
Construct( &Element(elem), src );
return elem;
}
#ifdef VALVE_RVALUE_REFS
template< typename T, class A >
inline int CUtlVector<T, A>::AddToTail( T&& src )
{
Assert( (&src < Base()) || (&src >= (Base() + Count())) );
int elem = m_Size;
GrowVector();
Construct( &Element( elem ), std::forward<T>( src ) );
return elem;
}
#endif
template< typename T, class A >
inline int CUtlVector<T, A>::AddMultipleToHead( int num )
{
return InsertMultipleBefore( 0, num );
}
template< typename T, class A >
inline int CUtlVector<T, A>::AddMultipleToTail( int num, const T *pToCopy )
{
Assert( !pToCopy || (pToCopy + num <= Base()) || (pToCopy >= (Base() + Count()) ) );
return InsertMultipleBefore( m_Size, num, pToCopy );
}
template< typename T, class A >
inline int CUtlVector<T, A>::InsertMultipleAfter( int elem, int num, const T *pToCopy )
{
return InsertMultipleBefore( elem + 1, num, pToCopy );
}
template< typename T, class A >
inline void CUtlVector<T, A>::SetCount( int count )
{
if ( count > m_Size )
{
int i = m_Size;
GrowVector( count - m_Size );
for ( ; i < m_Size; ++i )
{
Construct( m_Memory.Base() + i );
}
}
else if ( count >= 0 )
{
int nToRemove = m_Size - count;
m_Size = count;
while ( nToRemove-- )
{
Destruct( m_Memory.Base() + m_Size + nToRemove );
}
}
else
{
Assert( count >= 0 );
}
}
template< typename T, class A >
inline void CUtlVector<T, A>::CopyArray( const T *pArray, int size )
{
Assert( !pArray || (Base() >= (pArray + size)) || (pArray >= (Base() + Count()) ) );
SetCount( size );
for( int i=0; i < size; i++ )
{
m_Memory.Base()[i] = pArray[i];
}
}
template< typename T, class A >
inline void CUtlVector<T, A>::Swap( CUtlVector< T, A > &vec )
{
m_Memory.Swap( vec.m_Memory );
SWAP( m_Size, vec.m_Size );
}
template< typename T, class A >
inline int CUtlVector<T, A>::AddVectorToTail( CUtlVector const &src )
{
return AddMultipleToTail( src.Count(), src.Base() );
}
template< typename T, class A >
inline int CUtlVector<T, A>::InsertMultipleBefore( int elem, int num, const T *pToInsert )
{
if( num == 0 )
return elem;
Assert( (elem == Count()) || IsValidIndex(elem) );
GrowVector(num);
ShiftElementsRight(elem, num);
for (int i = 0; i < num; ++i)
Construct( &Element(elem+i) );
if ( pToInsert )
{
for ( int i=0; i < num; i++ )
{
Element( elem+i ) = pToInsert[i];
}
}
return elem;
}
template< typename T, class A >
inline int CUtlVector<T, A>::Find( const T& src ) const
{
for ( int i = 0; i < Count(); ++i )
{
if (Base()[i] == src)
return i;
}
return InvalidIndex();
}
#ifdef VALVE_RVALUE_REFS
template< typename T, class A >
template < typename TMatchFunc >
inline int CUtlVector<T, A>::FindMatch( TMatchFunc&& func ) const
{
for ( int i = 0; i < Count(); ++i )
{
if ( func( (*this)[i] ) )
return i;
}
return InvalidIndex();
}
#endif
template< typename T, class A >
inline bool CUtlVector<T, A>::HasElement( const T& src ) const
{
return ( Find(src) != InvalidIndex() );
}
template< typename T, class A >
inline void CUtlVector<T, A>::FastRemove( int elem )
{
Assert( IsValidIndex(elem) );
Destruct( &Base()[elem] );
if (m_Size > 0)
{
if ( elem != m_Size - 1 )
{
memcpy( (void *)&Base()[elem], (void *)&Base()[m_Size-1], sizeof(T) );
}
--m_Size;
}
}
template< typename T, class A >
inline void CUtlVector<T, A>::Remove( int elem )
{
Destruct( &Element(elem) );
ShiftElementsLeft(elem);
--m_Size;
}
template< typename T, class A >
inline bool CUtlVector<T, A>::FindAndRemove( const T& src )
{
int elem = Find( src );
if ( elem != InvalidIndex() )
{
Remove( elem );
return true;
}
return false;
}
template< typename T, class A >
inline bool CUtlVector<T, A>::FindAndFastRemove( const T& src )
{
int elem = Find( src );
if ( elem != InvalidIndex() )
{
FastRemove( elem );
return true;
}
return false;
}
template< typename T, class A >
void CUtlVector<T, A>::RemoveMultiple( int elem, int num )
{
Assert( elem >= 0 && num >= 0 && INT_MAX - elem >= num );
#if defined(COMPILER_GCC) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5))
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-overflow"
#endif
Assert( elem + num <= Count() );
#if defined(COMPILER_GCC) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5))
#pragma GCC diagnostic pop
#endif
for (int i = elem + num; --i >= elem; )
Destruct(&Base()[i]);
ShiftElementsLeft(elem, num);
m_Size -= num;
}
template< typename T, class A >
inline void CUtlVector<T, A>::RemoveMultipleFromTail( int num )
{
int nToRemove = Min( m_Size, num );
if ( nToRemove > 0 )
{
m_Size -= nToRemove;
while ( nToRemove-- )
{
Destruct( m_Memory.Base() + m_Size + nToRemove );
}
}
else
{
Assert( num >= 0 );
}
}
template< typename T, class A >
inline void CUtlVector<T, A>::RemoveAll()
{
for (int i = m_Size; --i >= 0; )
{
Destruct( m_Memory.Base() + i );
}
m_Size = 0;
}
template< typename T, class A >
inline void CUtlVector<T, A>::Purge()
{
RemoveAll();
m_Memory.Purge();
}
template< typename T, class A >
inline void CUtlVector<T, A>::PurgeAndDeleteElements()
{
for( int i=0; i < m_Size; i++ )
{
delete Element(i);
}
Purge();
}
template< typename T, class A >
inline void CUtlVector<T, A>::Compact()
{
m_Memory.Purge(m_Size);
}
template<class T> class CUtlVectorAutoPurge : public CUtlVector< T, CUtlMemory< T > >
{
public:
~CUtlVectorAutoPurge( void )
{
this->PurgeAndDeleteElements();
}
};
#ifdef DBGFLAG_VALIDATE
template< typename T, class A >
inline void CUtlVector<T, A>::Validate( CValidator &validator, const char *pchName )
{
#ifdef _WIN32
validator.Push( typeid(*this).raw_name(), this, pchName );
#else
validator.Push( typeid(*this).name(), this, pchName );
#endif
m_Memory.Validate( validator, "m_Memory" );
validator.Pop();
}
template< typename T, class A >
inline void CUtlVector<T, A>::ValidateSelfAndElements( CValidator &validator, const char *pchName )
{
#ifdef _WIN32
validator.Push( typeid(*this).raw_name(), this, pchName );
#else
validator.Push( typeid(*this).name(), this, pchName );
#endif
m_Memory.Validate( validator, "m_Memory" );
FOR_EACH_VEC( *this, i )
{
T &element = Element( i );
ValidateObj( element );
}
validator.Pop();
}
#endif
END_TIER1_NAMESPACE
#endif