summaryrefslogtreecommitdiff
path: root/public/tier1/utlstack.h
diff options
context:
space:
mode:
Diffstat (limited to 'public/tier1/utlstack.h')
-rw-r--r--public/tier1/utlstack.h331
1 files changed, 331 insertions, 0 deletions
diff --git a/public/tier1/utlstack.h b/public/tier1/utlstack.h
new file mode 100644
index 0000000..a46beb2
--- /dev/null
+++ b/public/tier1/utlstack.h
@@ -0,0 +1,331 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+// A stack based on a growable array
+//=============================================================================//
+
+#ifndef UTLSTACK_H
+#define UTLSTACK_H
+
+#include <assert.h>
+#include <string.h>
+#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 T, class M = CUtlMemory< T > >
+class CUtlStack
+{
+public:
+ // constructor, destructor
+ CUtlStack( int growSize = 0, int initSize = 0 );
+ ~CUtlStack();
+
+ void CopyFrom( const CUtlStack<T, M> &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< class T, class M >
+inline void CUtlStack<T,M>::ResetDbgInfo()
+{
+ m_pElements = m_Memory.Base();
+}
+
+//-----------------------------------------------------------------------------
+// constructor, destructor
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+CUtlStack<T,M>::CUtlStack( int growSize, int initSize ) :
+ m_Memory(growSize, initSize), m_Size(0)
+{
+ ResetDbgInfo();
+}
+
+template< class T, class M >
+CUtlStack<T,M>::~CUtlStack()
+{
+ Purge();
+}
+
+
+//-----------------------------------------------------------------------------
+// copy into
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+void CUtlStack<T,M>::CopyFrom( const CUtlStack<T, M> &from )
+{
+ Purge();
+ EnsureCapacity( from.Count() );
+ for ( int i = 0; i < from.Count(); i++ )
+ {
+ Push( from[i] );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// element access
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+inline T& CUtlStack<T,M>::operator[]( int i )
+{
+ assert( IsIdxValid(i) );
+ return m_Memory[i];
+}
+
+template< class T, class M >
+inline T const& CUtlStack<T,M>::operator[]( int i ) const
+{
+ assert( IsIdxValid(i) );
+ return m_Memory[i];
+}
+
+template< class T, class M >
+inline T& CUtlStack<T,M>::Element( int i )
+{
+ assert( IsIdxValid(i) );
+ return m_Memory[i];
+}
+
+template< class T, class M >
+inline T const& CUtlStack<T,M>::Element( int i ) const
+{
+ assert( IsIdxValid(i) );
+ return m_Memory[i];
+}
+
+
+//-----------------------------------------------------------------------------
+// Gets the base address (can change when adding elements!)
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+inline T* CUtlStack<T,M>::Base()
+{
+ return m_Memory.Base();
+}
+
+template< class T, class M >
+inline T const* CUtlStack<T,M>::Base() const
+{
+ return m_Memory.Base();
+}
+
+//-----------------------------------------------------------------------------
+// Returns the top of the stack
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+inline T& CUtlStack<T,M>::Top()
+{
+ assert( m_Size > 0 );
+ return Element(m_Size-1);
+}
+
+template< class T, class M >
+inline T const& CUtlStack<T,M>::Top() const
+{
+ assert( m_Size > 0 );
+ return Element(m_Size-1);
+}
+
+//-----------------------------------------------------------------------------
+// Size
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+inline int CUtlStack<T,M>::Count() const
+{
+ return m_Size;
+}
+
+
+//-----------------------------------------------------------------------------
+// Is element index valid?
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+inline bool CUtlStack<T,M>::IsIdxValid( int i ) const
+{
+ return (i >= 0) && (i < m_Size);
+}
+
+//-----------------------------------------------------------------------------
+// Grows the stack
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+void CUtlStack<T,M>::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< class T, class M >
+void CUtlStack<T,M>::EnsureCapacity( int num )
+{
+ m_Memory.EnsureCapacity(num);
+ ResetDbgInfo();
+}
+
+
+//-----------------------------------------------------------------------------
+// Adds an element, uses default constructor
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+int CUtlStack<T,M>::Push()
+{
+ GrowStack();
+ Construct( &Element(m_Size-1) );
+ return m_Size - 1;
+}
+
+//-----------------------------------------------------------------------------
+// Adds an element, uses copy constructor
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+int CUtlStack<T,M>::Push( T const& src )
+{
+ GrowStack();
+ CopyConstruct( &Element(m_Size-1), src );
+ return m_Size - 1;
+}
+
+
+//-----------------------------------------------------------------------------
+// Pops the stack
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+void CUtlStack<T,M>::Pop()
+{
+ assert( m_Size > 0 );
+ Destruct( &Element(m_Size-1) );
+ --m_Size;
+}
+
+template< class T, class M >
+void CUtlStack<T,M>::Pop( T& oldTop )
+{
+ assert( m_Size > 0 );
+ oldTop = Top();
+ Pop();
+}
+
+template< class T, class M >
+void CUtlStack<T,M>::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< class T, class M >
+void CUtlStack<T,M>::Clear()
+{
+ for (int i = m_Size; --i >= 0; )
+ Destruct(&Element(i));
+
+ m_Size = 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Memory deallocation
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+void CUtlStack<T,M>::Purge()
+{
+ Clear();
+ m_Memory.Purge( );
+ ResetDbgInfo();
+}
+
+#endif // UTLSTACK_H \ No newline at end of file