//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ // // A growable array class that maintains a free list and keeps elements // in the same location //=============================================================================// #ifndef UTLARRAY_H #define UTLARRAY_H #ifdef _WIN32 #pragma once #endif #include "tier0/dbg.h" #include "tier0/platform.h" #include "vstdlib/random.h" #define FOR_EACH_ARRAY(vecName, iteratorName) \ for (int iteratorName = 0; \ (vecName).IsUtlArray && iteratorName < (vecName).Count(); \ iteratorName++) #define FOR_EACH_ARRAY_BACK(vecName, iteratorName) \ for (int iteratorName = (vecName).Count() - 1; \ (vecName).IsUtlArray && iteratorName >= 0; iteratorName--) // utlarray derives from this so we can do the type check above struct base_array_t { public: static const bool IsUtlArray = true; // Used to match this at compiletime }; #if defined(GNUC) && defined(DEBUG) // gcc in debug doesn't optimize away the need for the storage of IsUtlArray so // make one here // as this is in a shared header use SELECTANY to make it throw away the dupe // symbols const bool base_array_t::IsUtlArray SELECTANY; #endif //----------------------------------------------------------------------------- template class CUtlArray : public base_array_t { public: typedef T ElemType_t; typedef T* iterator; typedef const T* const_iterator; CUtlArray(); CUtlArray(T* pMemory, size_t count); ~CUtlArray(); CUtlArray& operator=(const CUtlArray& other); CUtlArray(CUtlArray const& vec); // element access T& operator[](int i); const T& operator[](int i) const; T& Element(int i); const T& Element(int i) const; T& Random(); const T& Random() const; // STL compatible member functions. These allow easier use of std::sort // and they are forward compatible with the C++ 11 range-based for loops. iterator begin(); const_iterator begin() const; iterator end(); const_iterator end() const; T* Base(); const T* Base() const; // Returns the number of elements in the array, NumAllocated() is included // for consistency with UtlVector int Count() const; int NumAllocated() const; // Is element index valid? bool IsValidIndex(int i) const; static int InvalidIndex(); void CopyArray(const T* pArray, size_t count); void Swap(CUtlArray& vec); // Finds an element (element needs operator== defined) int Find(const T& src) const; void FillWithValue(const T& src); bool HasElement(const T& src) const; // calls delete on each element in it. void DeleteElements(); void Sort(int(__cdecl* pfnCompare)(const T*, const T*)); protected: T m_Memory[MAX_SIZE]; }; //----------------------------------------------------------------------------- // constructor, destructor //----------------------------------------------------------------------------- template inline CUtlArray::CUtlArray() {} template inline CUtlArray::CUtlArray(T* pMemory, size_t count) { CopyArray(pMemory, count); } template inline CUtlArray::~CUtlArray() {} template inline CUtlArray& CUtlArray::operator=( const CUtlArray& other) { if (this != &other) { for (size_t n = 0; n < MAX_SIZE; ++n) { m_Memory[n] = other.m_Memory[n]; } } return *this; } template inline CUtlArray::CUtlArray(CUtlArray const& vec) { for (size_t n = 0; n < MAX_SIZE; ++n) { m_Memory[n] = vec.m_Memory[n]; } } template typename CUtlArray::iterator CUtlArray::begin() { return Base(); } template typename CUtlArray::const_iterator CUtlArray::begin() const { return Base(); } template typename CUtlArray::iterator CUtlArray::end() { return Base() + Count(); } template typename CUtlArray::const_iterator CUtlArray::end() const { return Base() + Count(); } template inline T* CUtlArray::Base() { return &m_Memory[0]; } template inline const T* CUtlArray::Base() const { return &m_Memory[0]; } //----------------------------------------------------------------------------- // element access //----------------------------------------------------------------------------- template inline T& CUtlArray::operator[](int i) { Assert(IsValidIndex(i)); return m_Memory[i]; } template inline const T& CUtlArray::operator[](int i) const { Assert(IsValidIndex(i)); return m_Memory[i]; } template inline T& CUtlArray::Element(int i) { Assert(IsValidIndex(i)); return m_Memory[i]; } template inline const T& CUtlArray::Element(int i) const { Assert(IsValidIndex(i)); return m_Memory[i]; } template inline T& CUtlArray::Random() { Assert(MAX_SIZE > 0); return m_Memory[RandomInt(0, MAX_SIZE - 1)]; } template inline const T& CUtlArray::Random() const { Assert(MAX_SIZE > 0); return m_Memory[RandomInt(0, MAX_SIZE - 1)]; } //----------------------------------------------------------------------------- // Count //----------------------------------------------------------------------------- template inline int CUtlArray::Count() const { return (int)MAX_SIZE; } //----------------------------------------------------------------------------- template inline int CUtlArray::NumAllocated() const { return (int)MAX_SIZE; } //----------------------------------------------------------------------------- // Is element index valid? //----------------------------------------------------------------------------- template inline bool CUtlArray::IsValidIndex(int i) const { return (i >= 0) && (i < MAX_SIZE); } //----------------------------------------------------------------------------- // Returns in invalid index //----------------------------------------------------------------------------- template inline int CUtlArray::InvalidIndex() { return -1; } //----------------------------------------------------------------------------- // Sorts the vector //----------------------------------------------------------------------------- template void CUtlArray::Sort(int(__cdecl* pfnCompare)(const T*, const T*)) { typedef int(__cdecl * QSortCompareFunc_t)(const void*, const void*); if (Count() <= 1) return; qsort(Base(), Count(), sizeof(T), (QSortCompareFunc_t)(pfnCompare)); } template void CUtlArray::CopyArray(const T* pArray, size_t count) { Assert(count < MAX_SIZE); for (size_t n = 0; n < count; ++n) { m_Memory[n] = pArray[n]; } } template void CUtlArray::Swap(CUtlArray& vec) { for (size_t n = 0; n < MAX_SIZE; ++n) { V_swap(m_Memory[n], vec.m_Memory[n]); } } //----------------------------------------------------------------------------- // Finds an element (element needs operator== defined) //----------------------------------------------------------------------------- template int CUtlArray::Find(const T& src) const { for (int i = 0; i < Count(); ++i) { if (Element(i) == src) return i; } return -1; } template void CUtlArray::FillWithValue(const T& src) { for (int i = 0; i < Count(); i++) { Element(i) = src; } } template bool CUtlArray::HasElement(const T& src) const { return (Find(src) >= 0); } template inline void CUtlArray::DeleteElements() { for (int i = 0; i < MAX_SIZE; i++) { delete Element(i); } } #endif // UTLARRAY_H