/* * * Copyright (c) 1996-2002, Valve LLC. All rights reserved. * * This product contains software technology licensed from Id * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * All Rights Reserved. * * Use, distribution, and modification of this source code and/or resulting * object code is restricted to non-commercial enhancements to products from * Valve LLC. All other use, distribution, or modification is prohibited * without written permission from Valve LLC. * */ #pragma once // A growable array class that maintains a free list and keeps elements // in the same location #include "tier0/platform.h" #include "tier0/dbg.h" #include #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--) template class CUtlArray { public: typedef T ElemType_t; enum { IsUtlArray = true }; // Used to match this at compiletime 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; 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 Clear(); void RemoveAll(); void Swap(CUtlArray< T, MAX_SIZE> &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; // sort using std:: and expecting a "<" function to be defined for the type void Sort(); void Sort(bool (*pfnLessFunc)(const T &src1, const T &src2)); #if defined(_WIN32) void Sort(int (__cdecl *pfnCompare)(const T *, const T *)); #else void Sort(int (*pfnCompare)(const T *, const T *)); #endif // sort using std:: with a predicate. e.g. [] -> bool (const T &a, const T &b) const { return a < b; } template void SortPredicate(F &&predicate); protected: T m_Memory[MAX_SIZE]; }; // Constructor template inline CUtlArray::CUtlArray() { } template inline CUtlArray::CUtlArray(T *pMemory, size_t count) { CopyArray(pMemory, count); } // Destructor 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 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) { DbgAssert(IsValidIndex(i)); return m_Memory[i]; } template inline const T &CUtlArray::operator[](int i) const { DbgAssert(IsValidIndex(i)); return m_Memory[i]; } template inline T &CUtlArray::Element(int i) { DbgAssert(IsValidIndex(i)); return m_Memory[i]; } template inline const T &CUtlArray::Element(int i) const { DbgAssert(IsValidIndex(i)); return m_Memory[i]; } // 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; } // Sort methods template void CUtlArray::Sort() { std::sort(Base(), Base() + Count()); } template void CUtlArray::Sort(bool (*pfnLessFunc)(const T &src1, const T &src2)) { std::sort(Base(), Base() + Count(), [pfnLessFunc](const T &a, const T &b) -> bool { if (&a == &b) return false; return (*pfnLessFunc)(a, b); }); } #if defined(_WIN32) 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)); } #else // #if defined(_LINUX) template void CUtlArray::Sort(int (*pfnCompare)(const T *, const T *)) { typedef int (*QSortCompareFunc_t)(const void *, const void *); if (Count() <= 1) return; qsort(Base(), Count(), sizeof(T), (QSortCompareFunc_t)(pfnCompare)); } #endif // #if defined(_LINUX) template template void CUtlArray::SortPredicate(F &&predicate) { std::sort(Base(), Base() + Count(), predicate); } template void CUtlArray::CopyArray(const T *pArray, size_t count) { DbgAssert(count < MAX_SIZE); for (size_t n = 0; n < count; n++) m_Memory[n] = pArray[n]; } template void CUtlArray::Clear() { Q_memset(m_Memory, 0, MAX_SIZE * sizeof(T)); } template void CUtlArray::RemoveAll() { Clear(); } template void CUtlArray::Swap(CUtlArray< T, MAX_SIZE> &vec) { for (size_t n = 0; n < MAX_SIZE; n++) 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); }