#ifndef UTLSORTVECTOR_H #define UTLSORTVECTOR_H #ifdef _WIN32 #pragma once #endif #include "utlvector.h" #ifndef _WIN32 extern void* g_pUtlSortVectorQSortContext; #endif template class CUtlSortVectorDefaultLess { public: bool Less(const T& lhs, const T& rhs, void*) { return lhs < rhs; } }; template , class BaseVector = CUtlVector > class CUtlSortVector : public BaseVector { typedef BaseVector BaseClass; public: CUtlSortVector(int nGrowSize = 0, int initSize = 0); CUtlSortVector(T* pMemory, int numElements); int Insert(const T& src); int InsertIfNotFound(const T& src); template< typename TKey > int Find(const TKey& search) const; template< typename TKey > int FindLessOrEqual(const TKey& search) const; template< typename TKey > int FindLess(const TKey& search) const; void Remove(const T& search); void Remove(int i); void SetLessContext(void* pCtx); int InsertNoSort(const T& src); void RedoSort(bool bForceSort = false); int InsertAfter(int nElemIndex, const T& src); template< typename TKey > int FindUnsorted(const TKey& src) const; protected: CUtlSortVector(const CUtlSortVector&); int AddToHead(); int AddToTail(); int InsertBefore(int elem); int InsertAfter(int elem); int InsertBefore(int elem, const T& src); int AddToHead(const T& src); int AddToTail(const T& src); 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); int AddVectorToTail(CUtlVector const& src); struct QSortContext_t { void* m_pLessContext; LessFunc* m_pLessFunc; }; #ifdef _WIN32 static int CompareHelper(void* context, const T* lhs, const T* rhs) { QSortContext_t* ctx = reinterpret_cast(context); if (ctx->m_pLessFunc->Less(*lhs, *rhs, ctx->m_pLessContext)) return -1; if (ctx->m_pLessFunc->Less(*rhs, *lhs, ctx->m_pLessContext)) return 1; return 0; } #else static int CompareHelper(const T* lhs, const T* rhs) { QSortContext_t* ctx = reinterpret_cast(g_pUtlSortVectorQSortContext); if (ctx->m_pLessFunc->Less(*lhs, *rhs, ctx->m_pLessContext)) return -1; if (ctx->m_pLessFunc->Less(*rhs, *lhs, ctx->m_pLessContext)) return 1; return 0; } #endif void* m_pLessContext; bool m_bNeedsSort; private: private: template< typename TKey > int FindLessOrEqual(const TKey& search, bool* pFound) const; void QuickSort(LessFunc& less, int X, int I); }; template CUtlSortVector::CUtlSortVector(int nGrowSize, int initSize) : m_pLessContext(NULL), BaseVector(nGrowSize, initSize), m_bNeedsSort(false) { } template CUtlSortVector::CUtlSortVector(T* pMemory, int numElements) : m_pLessContext(NULL), BaseVector(pMemory, numElements), m_bNeedsSort(false) { } template void CUtlSortVector::SetLessContext(void* pCtx) { m_pLessContext = pCtx; } template int CUtlSortVector::Insert(const T& src) { AssertFatal(!m_bNeedsSort); int pos = FindLessOrEqual(src) + 1; this->GrowVector(); this->ShiftElementsRight(pos); CopyConstruct(&this->Element(pos), src); return pos; } template int CUtlSortVector::InsertNoSort(const T& src) { m_bNeedsSort = true; int lastElement = BaseVector::m_Size; this->GrowVector(); this->ShiftElementsRight(lastElement); CopyConstruct(&this->Element(lastElement), src); return lastElement; } template int CUtlSortVector::InsertIfNotFound(const T& src) { AssertFatal(!m_bNeedsSort); bool bFound; int pos = FindLessOrEqual(src, &bFound); if (bFound) return pos; ++pos; this->GrowVector(); this->ShiftElementsRight(pos); CopyConstruct(&this->Element(pos), src); return pos; } template int CUtlSortVector::InsertAfter(int nIndex, const T& src) { int nInsertedIndex = this->BaseClass::InsertAfter(nIndex, src); #ifdef DEBUG LessFunc less; if (nInsertedIndex > 0) { Assert(less.Less(this->Element(nInsertedIndex - 1), src, m_pLessContext)); } if (nInsertedIndex < BaseClass::Count() - 1) { Assert(less.Less(src, this->Element(nInsertedIndex + 1), m_pLessContext)); } #endif return nInsertedIndex; } template template < typename TKey > int CUtlSortVector::Find(const TKey& src) const { AssertFatal(!m_bNeedsSort); LessFunc less; int start = 0, end = this->Count() - 1; while (start <= end) { int mid = (start + end) >> 1; if (less.Less(this->Element(mid), src, m_pLessContext)) { start = mid + 1; } else if (less.Less(src, this->Element(mid), m_pLessContext)) { end = mid - 1; } else { return mid; } } return -1; } template< class T, class LessFunc, class BaseVector > template < typename TKey > int CUtlSortVector::FindUnsorted(const TKey& src) const { LessFunc less; int nCount = this->Count(); for (int i = 0; i < nCount; ++i) { if (less.Less(this->Element(i), src, m_pLessContext)) continue; if (less.Less(src, this->Element(i), m_pLessContext)) continue; return i; } return -1; } template template < typename TKey > int CUtlSortVector::FindLessOrEqual(const TKey& src, bool* pFound) const { AssertFatal(!m_bNeedsSort); LessFunc less; int start = 0, end = this->Count() - 1; while (start <= end) { int mid = (start + end) >> 1; if (less.Less(this->Element(mid), src, m_pLessContext)) { start = mid + 1; } else if (less.Less(src, this->Element(mid), m_pLessContext)) { end = mid - 1; } else { *pFound = true; return mid; } } *pFound = false; return end; } template template < typename TKey > int CUtlSortVector::FindLessOrEqual(const TKey& src) const { bool bFound; return FindLessOrEqual(src, &bFound); } template template < typename TKey > int CUtlSortVector::FindLess(const TKey& src) const { AssertFatal(!m_bNeedsSort); LessFunc less; int start = 0, end = this->Count() - 1; while (start <= end) { int mid = (start + end) >> 1; if (less.Less(this->Element(mid), src, m_pLessContext)) { start = mid + 1; } else { end = mid - 1; } } return end; } template void CUtlSortVector::Remove(const T& search) { AssertFatal(!m_bNeedsSort); int pos = Find(search); if (pos != -1) { BaseVector::Remove(pos); } } template void CUtlSortVector::Remove(int i) { BaseVector::Remove(i); } #endif