//========= 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