//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ // // A stack based on a growable array //=============================================================================// #ifndef UTLSTACK_H #define UTLSTACK_H #include #include #include "utlmemory.h" //----------------------------------------------------------------------------- // The CUtlStack class: // A growable stack class which doubles in size by default. // It will always keep all elements consecutive in memory, and may move the // elements around in memory (via a realloc) when elements are pushed or // popped. Clients should therefore refer to the elements of the stack // by index (they should *never* maintain pointers to elements in the stack). //----------------------------------------------------------------------------- template > class CUtlStack { public: // constructor, destructor CUtlStack(int growSize = 0, int initSize = 0); ~CUtlStack(); void CopyFrom(const CUtlStack& from); // element access T& operator[](int i); T const& operator[](int i) const; T& Element(int i); T const& Element(int i) const; // Gets the base address (can change when adding elements!) T* Base(); T const* Base() const; // Looks at the stack top T& Top(); T const& Top() const; // Size int Count() const; // Is element index valid? bool IsIdxValid(int i) const; // Adds an element, uses default constructor int Push(); // Adds an element, uses copy constructor int Push(T const& src); // Pops the stack void Pop(); void Pop(T& oldTop); void PopMultiple(int num); // Makes sure we have enough memory allocated to store a requested # of // elements void EnsureCapacity(int num); // Clears the stack, no deallocation void Clear(); // Memory deallocation void Purge(); private: // Grows the stack allocation void GrowStack(); // For easier access to the elements through the debugger void ResetDbgInfo(); M m_Memory; int m_Size; // For easier access to the elements through the debugger T* m_pElements; }; //----------------------------------------------------------------------------- // For easier access to the elements through the debugger //----------------------------------------------------------------------------- template inline void CUtlStack::ResetDbgInfo() { m_pElements = m_Memory.Base(); } //----------------------------------------------------------------------------- // constructor, destructor //----------------------------------------------------------------------------- template CUtlStack::CUtlStack(int growSize, int initSize) : m_Memory(growSize, initSize), m_Size(0) { ResetDbgInfo(); } template CUtlStack::~CUtlStack() { Purge(); } //----------------------------------------------------------------------------- // copy into //----------------------------------------------------------------------------- template void CUtlStack::CopyFrom(const CUtlStack& from) { Purge(); EnsureCapacity(from.Count()); for (int i = 0; i < from.Count(); i++) { Push(from[i]); } } //----------------------------------------------------------------------------- // element access //----------------------------------------------------------------------------- template inline T& CUtlStack::operator[](int i) { assert(IsIdxValid(i)); return m_Memory[i]; } template inline T const& CUtlStack::operator[](int i) const { assert(IsIdxValid(i)); return m_Memory[i]; } template inline T& CUtlStack::Element(int i) { assert(IsIdxValid(i)); return m_Memory[i]; } template inline T const& CUtlStack::Element(int i) const { assert(IsIdxValid(i)); return m_Memory[i]; } //----------------------------------------------------------------------------- // Gets the base address (can change when adding elements!) //----------------------------------------------------------------------------- template inline T* CUtlStack::Base() { return m_Memory.Base(); } template inline T const* CUtlStack::Base() const { return m_Memory.Base(); } //----------------------------------------------------------------------------- // Returns the top of the stack //----------------------------------------------------------------------------- template inline T& CUtlStack::Top() { assert(m_Size > 0); return Element(m_Size - 1); } template inline T const& CUtlStack::Top() const { assert(m_Size > 0); return Element(m_Size - 1); } //----------------------------------------------------------------------------- // Size //----------------------------------------------------------------------------- template inline int CUtlStack::Count() const { return m_Size; } //----------------------------------------------------------------------------- // Is element index valid? //----------------------------------------------------------------------------- template inline bool CUtlStack::IsIdxValid(int i) const { return (i >= 0) && (i < m_Size); } //----------------------------------------------------------------------------- // Grows the stack //----------------------------------------------------------------------------- template void CUtlStack::GrowStack() { if (m_Size >= m_Memory.NumAllocated()) m_Memory.Grow(); ++m_Size; ResetDbgInfo(); } //----------------------------------------------------------------------------- // Makes sure we have enough memory allocated to store a requested # of elements //----------------------------------------------------------------------------- template void CUtlStack::EnsureCapacity(int num) { m_Memory.EnsureCapacity(num); ResetDbgInfo(); } //----------------------------------------------------------------------------- // Adds an element, uses default constructor //----------------------------------------------------------------------------- template int CUtlStack::Push() { GrowStack(); Construct(&Element(m_Size - 1)); return m_Size - 1; } //----------------------------------------------------------------------------- // Adds an element, uses copy constructor //----------------------------------------------------------------------------- template int CUtlStack::Push(T const& src) { GrowStack(); CopyConstruct(&Element(m_Size - 1), src); return m_Size - 1; } //----------------------------------------------------------------------------- // Pops the stack //----------------------------------------------------------------------------- template void CUtlStack::Pop() { assert(m_Size > 0); Destruct(&Element(m_Size - 1)); --m_Size; } template void CUtlStack::Pop(T& oldTop) { assert(m_Size > 0); oldTop = Top(); Pop(); } template void CUtlStack::PopMultiple(int num) { assert(m_Size >= num); for (int i = 0; i < num; ++i) Destruct(&Element(m_Size - i - 1)); m_Size -= num; } //----------------------------------------------------------------------------- // Element removal //----------------------------------------------------------------------------- template void CUtlStack::Clear() { for (int i = m_Size; --i >= 0;) Destruct(&Element(i)); m_Size = 0; } //----------------------------------------------------------------------------- // Memory deallocation //----------------------------------------------------------------------------- template void CUtlStack::Purge() { Clear(); m_Memory.Purge(); ResetDbgInfo(); } #endif // UTLSTACK_H