Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

338 lines
9.1 KiB

  1. //====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======//
  2. //
  3. // Purpose: A dictionary mapping from symbol to structure
  4. //
  5. // $Header: $
  6. // $NoKeywords: $
  7. //=============================================================================//
  8. #ifndef UTLDICT_H
  9. #define UTLDICT_H
  10. #ifdef _WIN32
  11. #pragma once
  12. #endif
  13. #include "tier0/dbg.h"
  14. #include "tier1/utlmap.h"
  15. // Include this because tons of code was implicitly getting utlsymbol or utlvector via utldict.h
  16. #include "tier1/utlsymbol.h"
  17. #include "tier0/memdbgon.h"
  18. enum EDictCompareType
  19. {
  20. k_eDictCompareTypeCaseSensitive=0,
  21. k_eDictCompareTypeCaseInsensitive=1,
  22. k_eDictCompareTypeFilenames // Slashes and backslashes count as the same character..
  23. };
  24. //-----------------------------------------------------------------------------
  25. // A dictionary mapping from symbol to structure
  26. //-----------------------------------------------------------------------------
  27. #define FOR_EACH_DICT( dictName, iteratorName ) \
  28. for( int iteratorName=dictName.First(); iteratorName != dictName.InvalidIndex(); iteratorName = dictName.Next( iteratorName ) )
  29. // faster iteration, but in an unspecified order
  30. #define FOR_EACH_DICT_FAST( dictName, iteratorName ) \
  31. for ( int iteratorName = 0; iteratorName < dictName.MaxElement(); ++iteratorName ) if ( !dictName.IsValidIndex( iteratorName ) ) continue; else
  32. //-----------------------------------------------------------------------------
  33. // A dictionary mapping from symbol to structure
  34. //-----------------------------------------------------------------------------
  35. template <class T, class I = int >
  36. class CUtlDict
  37. {
  38. public:
  39. // constructor, destructor
  40. // Left at growSize = 0, the memory will first allocate 1 element and double in size
  41. // at each increment.
  42. CUtlDict( int compareType = k_eDictCompareTypeCaseInsensitive, int growSize = 0, int initSize = 0 );
  43. ~CUtlDict( );
  44. void EnsureCapacity( int );
  45. // gets particular elements
  46. T& Element( I i );
  47. const T& Element( I i ) const;
  48. T& operator[]( I i );
  49. const T& operator[]( I i ) const;
  50. // gets element names
  51. char *GetElementName( I i );
  52. char const *GetElementName( I i ) const;
  53. void SetElementName( I i, char const *pName );
  54. // Number of elements
  55. unsigned int Count() const;
  56. // Checks if a node is valid and in the tree
  57. bool IsValidIndex( I i ) const;
  58. // Invalid index
  59. static I InvalidIndex();
  60. // Insert method (inserts in order)
  61. I Insert( const char *pName, const T &element );
  62. I Insert( const char *pName );
  63. // Find method
  64. I Find( const char *pName ) const;
  65. // Remove methods
  66. void RemoveAt( I i );
  67. void Remove( const char *pName );
  68. void RemoveAll( );
  69. // Purge memory
  70. void Purge();
  71. void PurgeAndDeleteElements(); // Call delete on each element.
  72. // Iteration methods
  73. I First() const;
  74. I Next( I i ) const;
  75. // Nested typedefs, for code that might need
  76. // to fish out the index type from a given dict
  77. typedef I IndexType_t;
  78. protected:
  79. typedef CUtlMap<const char *, T, I> DictElementMap_t;
  80. DictElementMap_t m_Elements;
  81. };
  82. //-----------------------------------------------------------------------------
  83. // constructor, destructor
  84. //-----------------------------------------------------------------------------
  85. template <class T, class I>
  86. CUtlDict<T, I>::CUtlDict( int compareType, int growSize, int initSize ) : m_Elements( growSize, initSize )
  87. {
  88. if ( compareType == k_eDictCompareTypeFilenames )
  89. {
  90. m_Elements.SetLessFunc( CaselessStringLessThanIgnoreSlashes );
  91. }
  92. else if ( compareType == k_eDictCompareTypeCaseInsensitive )
  93. {
  94. m_Elements.SetLessFunc( CaselessStringLessThan );
  95. }
  96. else
  97. {
  98. m_Elements.SetLessFunc( StringLessThan );
  99. }
  100. }
  101. template <class T, class I>
  102. CUtlDict<T, I>::~CUtlDict()
  103. {
  104. Purge();
  105. }
  106. template <class T, class I>
  107. inline void CUtlDict<T, I>::EnsureCapacity( int num )
  108. {
  109. return m_Elements.EnsureCapacity( num );
  110. }
  111. //-----------------------------------------------------------------------------
  112. // gets particular elements
  113. //-----------------------------------------------------------------------------
  114. template <class T, class I>
  115. inline T& CUtlDict<T, I>::Element( I i )
  116. {
  117. return m_Elements[i];
  118. }
  119. template <class T, class I>
  120. inline const T& CUtlDict<T, I>::Element( I i ) const
  121. {
  122. return m_Elements[i];
  123. }
  124. //-----------------------------------------------------------------------------
  125. // gets element names
  126. //-----------------------------------------------------------------------------
  127. template <class T, class I>
  128. inline char *CUtlDict<T, I>::GetElementName( I i )
  129. {
  130. return (char *)m_Elements.Key( i );
  131. }
  132. template <class T, class I>
  133. inline char const *CUtlDict<T, I>::GetElementName( I i ) const
  134. {
  135. return m_Elements.Key( i );
  136. }
  137. template <class T, class I>
  138. inline T& CUtlDict<T, I>::operator[]( I i )
  139. {
  140. return Element(i);
  141. }
  142. template <class T, class I>
  143. inline const T & CUtlDict<T, I>::operator[]( I i ) const
  144. {
  145. return Element(i);
  146. }
  147. template <class T, class I>
  148. inline void CUtlDict<T, I>::SetElementName( I i, char const *pName )
  149. {
  150. MEM_ALLOC_CREDIT_CLASS();
  151. // TODO: This makes a copy of the old element
  152. // TODO: This relies on the rb tree putting the most recently
  153. // removed element at the head of the insert list
  154. free( (void *)m_Elements.Key( i ) );
  155. m_Elements.Reinsert( strdup( pName ), i );
  156. }
  157. //-----------------------------------------------------------------------------
  158. // Num elements
  159. //-----------------------------------------------------------------------------
  160. template <class T, class I>
  161. inline unsigned int CUtlDict<T, I>::Count() const
  162. {
  163. return m_Elements.Count();
  164. }
  165. //-----------------------------------------------------------------------------
  166. // Checks if a node is valid and in the tree
  167. //-----------------------------------------------------------------------------
  168. template <class T, class I>
  169. inline bool CUtlDict<T, I>::IsValidIndex( I i ) const
  170. {
  171. return m_Elements.IsValidIndex(i);
  172. }
  173. //-----------------------------------------------------------------------------
  174. // Invalid index
  175. //-----------------------------------------------------------------------------
  176. template <class T, class I>
  177. inline I CUtlDict<T, I>::InvalidIndex()
  178. {
  179. return DictElementMap_t::InvalidIndex();
  180. }
  181. //-----------------------------------------------------------------------------
  182. // Delete a node from the tree
  183. //-----------------------------------------------------------------------------
  184. template <class T, class I>
  185. void CUtlDict<T, I>::RemoveAt(I elem)
  186. {
  187. free( (void *)m_Elements.Key( elem ) );
  188. m_Elements.RemoveAt(elem);
  189. }
  190. //-----------------------------------------------------------------------------
  191. // remove a node in the tree
  192. //-----------------------------------------------------------------------------
  193. template <class T, class I> void CUtlDict<T, I>::Remove( const char *search )
  194. {
  195. I node = Find( search );
  196. if (node != InvalidIndex())
  197. {
  198. RemoveAt(node);
  199. }
  200. }
  201. //-----------------------------------------------------------------------------
  202. // Removes all nodes from the tree
  203. //-----------------------------------------------------------------------------
  204. template <class T, class I>
  205. void CUtlDict<T, I>::RemoveAll()
  206. {
  207. typename DictElementMap_t::IndexType_t index = m_Elements.FirstInorder();
  208. while ( index != m_Elements.InvalidIndex() )
  209. {
  210. const char *pKey = m_Elements.Key( index );
  211. free( const_cast<char*>(pKey) );
  212. index = m_Elements.NextInorder( index );
  213. }
  214. m_Elements.RemoveAll();
  215. }
  216. template <class T, class I>
  217. void CUtlDict<T, I>::Purge()
  218. {
  219. RemoveAll();
  220. }
  221. template <class T, class I>
  222. void CUtlDict<T, I>::PurgeAndDeleteElements()
  223. {
  224. // Delete all the elements.
  225. I index = m_Elements.FirstInorder();
  226. while ( index != m_Elements.InvalidIndex() )
  227. {
  228. const char* pKey = m_Elements.Key( index );
  229. free( const_cast<char*>(pKey) );
  230. delete m_Elements[index];
  231. index = m_Elements.NextInorder( index );
  232. }
  233. m_Elements.RemoveAll();
  234. }
  235. //-----------------------------------------------------------------------------
  236. // inserts a node into the tree
  237. //-----------------------------------------------------------------------------
  238. template <class T, class I>
  239. I CUtlDict<T, I>::Insert( const char *pName, const T &element )
  240. {
  241. MEM_ALLOC_CREDIT_CLASS();
  242. return m_Elements.Insert( strdup( pName ), element );
  243. }
  244. template <class T, class I>
  245. I CUtlDict<T, I>::Insert( const char *pName )
  246. {
  247. MEM_ALLOC_CREDIT_CLASS();
  248. return m_Elements.Insert( strdup( pName ) );
  249. }
  250. //-----------------------------------------------------------------------------
  251. // finds a node in the tree
  252. //-----------------------------------------------------------------------------
  253. template <class T, class I>
  254. I CUtlDict<T, I>::Find( const char *pName ) const
  255. {
  256. MEM_ALLOC_CREDIT_CLASS();
  257. if ( pName )
  258. return m_Elements.Find( pName );
  259. else
  260. return InvalidIndex();
  261. }
  262. //-----------------------------------------------------------------------------
  263. // Iteration methods
  264. //-----------------------------------------------------------------------------
  265. template <class T, class I>
  266. I CUtlDict<T, I>::First() const
  267. {
  268. return m_Elements.FirstInorder();
  269. }
  270. template <class T, class I>
  271. I CUtlDict<T, I>::Next( I i ) const
  272. {
  273. return m_Elements.NextInorder(i);
  274. }
  275. #include "tier0/memdbgoff.h"
  276. #endif // UTLDICT_H