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.

358 lines
9.8 KiB

  1. //========= Copyright 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. // Number of allocated slots
  57. I MaxElement() const;
  58. // Checks if a node is valid and in the tree
  59. bool IsValidIndex( I i ) const;
  60. // Invalid index
  61. static I InvalidIndex();
  62. // Insert method (inserts in order)
  63. I Insert( const char *pName, const T &element );
  64. I Insert( const char *pName );
  65. // Find method
  66. I Find( const char *pName ) const;
  67. bool HasElement( const char *pName ) const;
  68. // Remove methods
  69. void RemoveAt( I i );
  70. void Remove( const char *pName );
  71. void RemoveAll( );
  72. // Purge memory
  73. void Purge();
  74. void PurgeAndDeleteElements(); // Call delete on each element.
  75. // Iteration methods
  76. I First() const;
  77. I Next( I i ) const;
  78. // Nested typedefs, for code that might need
  79. // to fish out the index type from a given dict
  80. typedef I IndexType_t;
  81. protected:
  82. typedef CUtlMap<const char *, T, I> DictElementMap_t;
  83. DictElementMap_t m_Elements;
  84. };
  85. //-----------------------------------------------------------------------------
  86. // constructor, destructor
  87. //-----------------------------------------------------------------------------
  88. template <class T, class I>
  89. CUtlDict<T, I>::CUtlDict( int compareType, int growSize, int initSize ) : m_Elements( growSize, initSize )
  90. {
  91. if ( compareType == k_eDictCompareTypeFilenames )
  92. {
  93. m_Elements.SetLessFunc( CaselessStringLessThanIgnoreSlashes );
  94. }
  95. else if ( compareType == k_eDictCompareTypeCaseInsensitive )
  96. {
  97. m_Elements.SetLessFunc( CaselessStringLessThan );
  98. }
  99. else
  100. {
  101. m_Elements.SetLessFunc( StringLessThan );
  102. }
  103. }
  104. template <class T, class I>
  105. CUtlDict<T, I>::~CUtlDict()
  106. {
  107. Purge();
  108. }
  109. template <class T, class I>
  110. inline void CUtlDict<T, I>::EnsureCapacity( int num )
  111. {
  112. return m_Elements.EnsureCapacity( num );
  113. }
  114. //-----------------------------------------------------------------------------
  115. // gets particular elements
  116. //-----------------------------------------------------------------------------
  117. template <class T, class I>
  118. inline T& CUtlDict<T, I>::Element( I i )
  119. {
  120. return m_Elements[i];
  121. }
  122. template <class T, class I>
  123. inline const T& CUtlDict<T, I>::Element( I i ) const
  124. {
  125. return m_Elements[i];
  126. }
  127. //-----------------------------------------------------------------------------
  128. // gets element names
  129. //-----------------------------------------------------------------------------
  130. template <class T, class I>
  131. inline char *CUtlDict<T, I>::GetElementName( I i )
  132. {
  133. return (char *)m_Elements.Key( i );
  134. }
  135. template <class T, class I>
  136. inline char const *CUtlDict<T, I>::GetElementName( I i ) const
  137. {
  138. return m_Elements.Key( i );
  139. }
  140. template <class T, class I>
  141. inline T& CUtlDict<T, I>::operator[]( I i )
  142. {
  143. return Element(i);
  144. }
  145. template <class T, class I>
  146. inline const T & CUtlDict<T, I>::operator[]( I i ) const
  147. {
  148. return Element(i);
  149. }
  150. template <class T, class I>
  151. inline void CUtlDict<T, I>::SetElementName( I i, char const *pName )
  152. {
  153. MEM_ALLOC_CREDIT_CLASS();
  154. // TODO: This makes a copy of the old element
  155. // TODO: This relies on the rb tree putting the most recently
  156. // removed element at the head of the insert list
  157. free( (void *)m_Elements.Key( i ) );
  158. m_Elements.Reinsert( strdup( pName ), i );
  159. }
  160. //-----------------------------------------------------------------------------
  161. // Num elements
  162. //-----------------------------------------------------------------------------
  163. template <class T, class I>
  164. inline unsigned int CUtlDict<T, I>::Count() const
  165. {
  166. return m_Elements.Count();
  167. }
  168. //-----------------------------------------------------------------------------
  169. // Number of allocated slots
  170. //-----------------------------------------------------------------------------
  171. template <class T, class I>
  172. inline I CUtlDict<T, I>::MaxElement() const
  173. {
  174. return m_Elements.MaxElement();
  175. }
  176. //-----------------------------------------------------------------------------
  177. // Checks if a node is valid and in the tree
  178. //-----------------------------------------------------------------------------
  179. template <class T, class I>
  180. inline bool CUtlDict<T, I>::IsValidIndex( I i ) const
  181. {
  182. return m_Elements.IsValidIndex(i);
  183. }
  184. //-----------------------------------------------------------------------------
  185. // Invalid index
  186. //-----------------------------------------------------------------------------
  187. template <class T, class I>
  188. inline I CUtlDict<T, I>::InvalidIndex()
  189. {
  190. return DictElementMap_t::InvalidIndex();
  191. }
  192. //-----------------------------------------------------------------------------
  193. // Delete a node from the tree
  194. //-----------------------------------------------------------------------------
  195. template <class T, class I>
  196. void CUtlDict<T, I>::RemoveAt(I elem)
  197. {
  198. free( (void *)m_Elements.Key( elem ) );
  199. m_Elements.RemoveAt(elem);
  200. }
  201. //-----------------------------------------------------------------------------
  202. // remove a node in the tree
  203. //-----------------------------------------------------------------------------
  204. template <class T, class I> void CUtlDict<T, I>::Remove( const char *search )
  205. {
  206. I node = Find( search );
  207. if (node != InvalidIndex())
  208. {
  209. RemoveAt(node);
  210. }
  211. }
  212. //-----------------------------------------------------------------------------
  213. // Removes all nodes from the tree
  214. //-----------------------------------------------------------------------------
  215. template <class T, class I>
  216. void CUtlDict<T, I>::RemoveAll()
  217. {
  218. typename DictElementMap_t::IndexType_t index = m_Elements.FirstInorder();
  219. while ( index != m_Elements.InvalidIndex() )
  220. {
  221. free( (void *)m_Elements.Key( index ) );
  222. index = m_Elements.NextInorder( index );
  223. }
  224. m_Elements.RemoveAll();
  225. }
  226. template <class T, class I>
  227. void CUtlDict<T, I>::Purge()
  228. {
  229. RemoveAll();
  230. }
  231. template <class T, class I>
  232. void CUtlDict<T, I>::PurgeAndDeleteElements()
  233. {
  234. // Delete all the elements.
  235. I index = m_Elements.FirstInorder();
  236. while ( index != m_Elements.InvalidIndex() )
  237. {
  238. free( (void *)m_Elements.Key( index ) );
  239. delete m_Elements[index];
  240. index = m_Elements.NextInorder( index );
  241. }
  242. m_Elements.RemoveAll();
  243. }
  244. //-----------------------------------------------------------------------------
  245. // inserts a node into the tree
  246. //-----------------------------------------------------------------------------
  247. template <class T, class I>
  248. I CUtlDict<T, I>::Insert( const char *pName, const T &element )
  249. {
  250. MEM_ALLOC_CREDIT_CLASS();
  251. return m_Elements.Insert( strdup( pName ), element );
  252. }
  253. template <class T, class I>
  254. I CUtlDict<T, I>::Insert( const char *pName )
  255. {
  256. MEM_ALLOC_CREDIT_CLASS();
  257. return m_Elements.Insert( strdup( pName ) );
  258. }
  259. //-----------------------------------------------------------------------------
  260. // finds a node in the tree
  261. //-----------------------------------------------------------------------------
  262. template <class T, class I>
  263. I CUtlDict<T, I>::Find( const char *pName ) const
  264. {
  265. MEM_ALLOC_CREDIT_CLASS();
  266. if ( pName )
  267. return m_Elements.Find( pName );
  268. else
  269. return InvalidIndex();
  270. }
  271. //-----------------------------------------------------------------------------
  272. // returns true if we already have this node
  273. //-----------------------------------------------------------------------------
  274. template <class T, class I>
  275. bool CUtlDict<T, I>::HasElement( const char *pName ) const
  276. {
  277. if ( pName )
  278. return m_Elements.IsValidIndex( m_Elements.Find( pName ) );
  279. else
  280. return false;
  281. }
  282. //-----------------------------------------------------------------------------
  283. // Iteration methods
  284. //-----------------------------------------------------------------------------
  285. template <class T, class I>
  286. I CUtlDict<T, I>::First() const
  287. {
  288. return m_Elements.FirstInorder();
  289. }
  290. template <class T, class I>
  291. I CUtlDict<T, I>::Next( I i ) const
  292. {
  293. return m_Elements.NextInorder(i);
  294. }
  295. #include "tier0/memdbgoff.h"
  296. #endif // UTLDICT_H