//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: A dictionary mapping from symbol to structure // // $Header: $ // $NoKeywords: $ //=============================================================================// #ifndef UTLDICT_H #define UTLDICT_H #ifdef _WIN32 #pragma once #endif #include "tier0/dbg.h" #include "tier1/utlmap.h" // Include this because tons of code was implicitly getting utlsymbol or utlvector via utldict.h #include "tier1/utlsymbol.h" #include "tier0/memdbgon.h" enum EDictCompareType { k_eDictCompareTypeCaseSensitive=0, k_eDictCompareTypeCaseInsensitive=1, k_eDictCompareTypeFilenames // Slashes and backslashes count as the same character.. }; //----------------------------------------------------------------------------- // A dictionary mapping from symbol to structure //----------------------------------------------------------------------------- #define FOR_EACH_DICT( dictName, iteratorName ) \ for( int iteratorName=dictName.First(); iteratorName != dictName.InvalidIndex(); iteratorName = dictName.Next( iteratorName ) ) // faster iteration, but in an unspecified order #define FOR_EACH_DICT_FAST( dictName, iteratorName ) \ for ( int iteratorName = 0; iteratorName < dictName.MaxElement(); ++iteratorName ) if ( !dictName.IsValidIndex( iteratorName ) ) continue; else //----------------------------------------------------------------------------- // A dictionary mapping from symbol to structure //----------------------------------------------------------------------------- template class CUtlDict { public: // constructor, destructor // Left at growSize = 0, the memory will first allocate 1 element and double in size // at each increment. CUtlDict( int compareType = k_eDictCompareTypeCaseInsensitive, int growSize = 0, int initSize = 0 ); ~CUtlDict( ); void EnsureCapacity( int ); // gets particular elements T& Element( I i ); const T& Element( I i ) const; T& operator[]( I i ); const T& operator[]( I i ) const; // gets element names char *GetElementName( I i ); char const *GetElementName( I i ) const; void SetElementName( I i, char const *pName ); // Number of elements unsigned int Count() const; // Number of allocated slots I MaxElement() const; // Checks if a node is valid and in the tree bool IsValidIndex( I i ) const; // Invalid index static I InvalidIndex(); // Insert method (inserts in order) I Insert( const char *pName, const T &element ); I Insert( const char *pName ); // Find method I Find( const char *pName ) const; bool HasElement( const char *pName ) const; // Remove methods void RemoveAt( I i ); void Remove( const char *pName ); void RemoveAll( ); // Purge memory void Purge(); void PurgeAndDeleteElements(); // Call delete on each element. // Iteration methods I First() const; I Next( I i ) const; // Nested typedefs, for code that might need // to fish out the index type from a given dict typedef I IndexType_t; protected: typedef CUtlMap DictElementMap_t; DictElementMap_t m_Elements; }; //----------------------------------------------------------------------------- // constructor, destructor //----------------------------------------------------------------------------- template CUtlDict::CUtlDict( int compareType, int growSize, int initSize ) : m_Elements( growSize, initSize ) { if ( compareType == k_eDictCompareTypeFilenames ) { m_Elements.SetLessFunc( CaselessStringLessThanIgnoreSlashes ); } else if ( compareType == k_eDictCompareTypeCaseInsensitive ) { m_Elements.SetLessFunc( CaselessStringLessThan ); } else { m_Elements.SetLessFunc( StringLessThan ); } } template CUtlDict::~CUtlDict() { Purge(); } template inline void CUtlDict::EnsureCapacity( int num ) { return m_Elements.EnsureCapacity( num ); } //----------------------------------------------------------------------------- // gets particular elements //----------------------------------------------------------------------------- template inline T& CUtlDict::Element( I i ) { return m_Elements[i]; } template inline const T& CUtlDict::Element( I i ) const { return m_Elements[i]; } //----------------------------------------------------------------------------- // gets element names //----------------------------------------------------------------------------- template inline char *CUtlDict::GetElementName( I i ) { return (char *)m_Elements.Key( i ); } template inline char const *CUtlDict::GetElementName( I i ) const { return m_Elements.Key( i ); } template inline T& CUtlDict::operator[]( I i ) { return Element(i); } template inline const T & CUtlDict::operator[]( I i ) const { return Element(i); } template inline void CUtlDict::SetElementName( I i, char const *pName ) { MEM_ALLOC_CREDIT_CLASS(); // TODO: This makes a copy of the old element // TODO: This relies on the rb tree putting the most recently // removed element at the head of the insert list free( (void *)m_Elements.Key( i ) ); m_Elements.Reinsert( strdup( pName ), i ); } //----------------------------------------------------------------------------- // Num elements //----------------------------------------------------------------------------- template inline unsigned int CUtlDict::Count() const { return m_Elements.Count(); } //----------------------------------------------------------------------------- // Number of allocated slots //----------------------------------------------------------------------------- template inline I CUtlDict::MaxElement() const { return m_Elements.MaxElement(); } //----------------------------------------------------------------------------- // Checks if a node is valid and in the tree //----------------------------------------------------------------------------- template inline bool CUtlDict::IsValidIndex( I i ) const { return m_Elements.IsValidIndex(i); } //----------------------------------------------------------------------------- // Invalid index //----------------------------------------------------------------------------- template inline I CUtlDict::InvalidIndex() { return DictElementMap_t::InvalidIndex(); } //----------------------------------------------------------------------------- // Delete a node from the tree //----------------------------------------------------------------------------- template void CUtlDict::RemoveAt(I elem) { free( (void *)m_Elements.Key( elem ) ); m_Elements.RemoveAt(elem); } //----------------------------------------------------------------------------- // remove a node in the tree //----------------------------------------------------------------------------- template void CUtlDict::Remove( const char *search ) { I node = Find( search ); if (node != InvalidIndex()) { RemoveAt(node); } } //----------------------------------------------------------------------------- // Removes all nodes from the tree //----------------------------------------------------------------------------- template void CUtlDict::RemoveAll() { typename DictElementMap_t::IndexType_t index = m_Elements.FirstInorder(); while ( index != m_Elements.InvalidIndex() ) { free( (void *)m_Elements.Key( index ) ); index = m_Elements.NextInorder( index ); } m_Elements.RemoveAll(); } template void CUtlDict::Purge() { RemoveAll(); } template void CUtlDict::PurgeAndDeleteElements() { // Delete all the elements. I index = m_Elements.FirstInorder(); while ( index != m_Elements.InvalidIndex() ) { free( (void *)m_Elements.Key( index ) ); delete m_Elements[index]; index = m_Elements.NextInorder( index ); } m_Elements.RemoveAll(); } //----------------------------------------------------------------------------- // inserts a node into the tree //----------------------------------------------------------------------------- template I CUtlDict::Insert( const char *pName, const T &element ) { MEM_ALLOC_CREDIT_CLASS(); return m_Elements.Insert( strdup( pName ), element ); } template I CUtlDict::Insert( const char *pName ) { MEM_ALLOC_CREDIT_CLASS(); return m_Elements.Insert( strdup( pName ) ); } //----------------------------------------------------------------------------- // finds a node in the tree //----------------------------------------------------------------------------- template I CUtlDict::Find( const char *pName ) const { MEM_ALLOC_CREDIT_CLASS(); if ( pName ) return m_Elements.Find( pName ); else return InvalidIndex(); } //----------------------------------------------------------------------------- // returns true if we already have this node //----------------------------------------------------------------------------- template bool CUtlDict::HasElement( const char *pName ) const { if ( pName ) return m_Elements.IsValidIndex( m_Elements.Find( pName ) ); else return false; } //----------------------------------------------------------------------------- // Iteration methods //----------------------------------------------------------------------------- template I CUtlDict::First() const { return m_Elements.FirstInorder(); } template I CUtlDict::Next( I i ) const { return m_Elements.NextInorder(i); } #include "tier0/memdbgoff.h" #endif // UTLDICT_H