mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
Add full CUtlDict implementation
CUtlDict from the SourceSDK.
This commit is contained in:
parent
a68a0c511a
commit
2cfed900d0
@ -6,22 +6,357 @@
|
||||
// $NoKeywords: $
|
||||
//===========================================================================//
|
||||
|
||||
#pragma once
|
||||
#ifndef UTLDICT_H
|
||||
#define UTLDICT_H
|
||||
|
||||
template <class T, class I>
|
||||
#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 T, class I = int >
|
||||
class CUtlDict
|
||||
{
|
||||
public:
|
||||
CUtlDict() {};
|
||||
CUtlDict<T, I>(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<const char *, T, I> DictElementMap_t;
|
||||
DictElementMap_t m_Elements;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// constructor, destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
T CUtlDict<T, I>::Find(I entry)
|
||||
CUtlDict<T, I>::CUtlDict( int compareType, int growSize, int initSize ) : m_Elements( growSize, initSize )
|
||||
{
|
||||
return *(T*)(m_Elements + 24 * entry + 16);
|
||||
}
|
||||
if ( compareType == k_eDictCompareTypeFilenames )
|
||||
{
|
||||
m_Elements.SetLessFunc( CaselessStringLessThanIgnoreSlashes );
|
||||
}
|
||||
else if ( compareType == k_eDictCompareTypeCaseInsensitive )
|
||||
{
|
||||
m_Elements.SetLessFunc( CaselessStringLessThan );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Elements.SetLessFunc( StringLessThan );
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
CUtlDict<T, I>::~CUtlDict()
|
||||
{
|
||||
Purge();
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
inline void CUtlDict<T, I>::EnsureCapacity( int num )
|
||||
{
|
||||
return m_Elements.EnsureCapacity( num );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// gets particular elements
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
inline T& CUtlDict<T, I>::Element( I i )
|
||||
{
|
||||
return m_Elements[i];
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
inline const T& CUtlDict<T, I>::Element( I i ) const
|
||||
{
|
||||
return m_Elements[i];
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// gets element names
|
||||
//-----------------------------------------------------------------------------
|
||||
/*template <class T, class I>
|
||||
inline char *CUtlDict<T, I>::GetElementName( I i )
|
||||
{
|
||||
return const_cast< char* >( m_Elements.Key( i ) );
|
||||
}*/
|
||||
|
||||
template <class T, class I>
|
||||
inline char const *CUtlDict<T, I>::GetElementName( I i ) const
|
||||
{
|
||||
return m_Elements.Key( i );
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
inline T& CUtlDict<T, I>::operator[]( I i )
|
||||
{
|
||||
return Element(i);
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
inline const T & CUtlDict<T, I>::operator[]( I i ) const
|
||||
{
|
||||
return Element(i);
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
inline void CUtlDict<T, I>::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 <class T, class I>
|
||||
inline unsigned int CUtlDict<T, I>::Count() const
|
||||
{
|
||||
return m_Elements.Count();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Number of allocated slots
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
inline I CUtlDict<T, I>::MaxElement() const
|
||||
{
|
||||
return m_Elements.MaxElement();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Checks if a node is valid and in the tree
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
inline bool CUtlDict<T, I>::IsValidIndex( I i ) const
|
||||
{
|
||||
return m_Elements.IsValidIndex(i);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Invalid index
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
inline I CUtlDict<T, I>::InvalidIndex()
|
||||
{
|
||||
return DictElementMap_t::InvalidIndex();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Delete a node from the tree
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
void CUtlDict<T, I>::RemoveAt(I elem)
|
||||
{
|
||||
free( const_cast< char* >( m_Elements.Key( elem ) ) );
|
||||
m_Elements.RemoveAt(elem);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// remove a node in the tree
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I> void CUtlDict<T, I>::Remove( const char *search )
|
||||
{
|
||||
I node = Find( search );
|
||||
if (node != InvalidIndex())
|
||||
{
|
||||
RemoveAt(node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Removes all nodes from the tree
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
void CUtlDict<T, I>::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 <class T, class I>
|
||||
void CUtlDict<T, I>::Purge()
|
||||
{
|
||||
RemoveAll();
|
||||
}
|
||||
|
||||
|
||||
template <class T, class I>
|
||||
void CUtlDict<T, I>::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 <class T, class I>
|
||||
I CUtlDict<T, I>::Insert( const char *pName, const T &element )
|
||||
{
|
||||
MEM_ALLOC_CREDIT_CLASS();
|
||||
return m_Elements.Insert( strdup( pName ), element );
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
I CUtlDict<T, I>::Insert( const char *pName )
|
||||
{
|
||||
MEM_ALLOC_CREDIT_CLASS();
|
||||
return m_Elements.Insert( strdup( pName ) );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// finds a node in the tree
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
I CUtlDict<T, I>::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 <class T, class I>
|
||||
bool CUtlDict<T, I>::HasElement( const char *pName ) const
|
||||
{
|
||||
if ( pName )
|
||||
return m_Elements.IsValidIndex( m_Elements.Find( pName ) );
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Iteration methods
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
I CUtlDict<T, I>::First() const
|
||||
{
|
||||
return m_Elements.FirstInorder();
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
I CUtlDict<T, I>::Next( I i ) const
|
||||
{
|
||||
return m_Elements.NextInorder(i);
|
||||
}
|
||||
|
||||
#include "tier0/memdbgoff.h"
|
||||
|
||||
#endif // UTLDICT_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user