From 2cfed900d073dbed96a917ecda4b799cb23f169a Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Mon, 19 Jun 2023 11:23:22 +0200 Subject: [PATCH] Add full CUtlDict implementation CUtlDict from the SourceSDK. --- r5dev/public/tier1/utldict.h | 355 ++++++++++++++++++++++++++++++++++- 1 file changed, 345 insertions(+), 10 deletions(-) diff --git a/r5dev/public/tier1/utldict.h b/r5dev/public/tier1/utldict.h index fc7595f0..81680e87 100644 --- a/r5dev/public/tier1/utldict.h +++ b/r5dev/public/tier1/utldict.h @@ -6,22 +6,357 @@ // $NoKeywords: $ //===========================================================================// -#pragma once +#ifndef UTLDICT_H +#define UTLDICT_H -template +#ifdef _WIN32 +#pragma once +#endif + +#include "tier0/dbg.h" +#include "tier1/utlmap.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 +//----------------------------------------------------------------------------- + +// This is a useful macro to iterate from start to end in order in a map +#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: - CUtlDict() {}; - CUtlDict(uintptr_t ptr) : m_Elements(ptr) {}; - T Find(I entry); + typedef const char* KeyType_t; + typedef T ElemType_t; -private: - uintptr_t m_Elements; + // 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 -T CUtlDict::Find(I entry) +CUtlDict::CUtlDict( int compareType, int growSize, int initSize ) : m_Elements( growSize, initSize ) { - return *(T*)(m_Elements + 24 * entry + 16); -} \ No newline at end of file + 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 const_cast< 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( const_cast< char* >( 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( const_cast< char* >( 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() ) + { + const char* p = m_Elements.Key( index ); + free( const_cast< char* >( p ) ); + 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() ) + { + const char* p = m_Elements.Key( index ); + free( const_cast< char* >( p ) ); + 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