Counter Strike : Global Offensive Source Code
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.

342 lines
9.9 KiB

  1. //========== Copyright � 2005, Valve Corporation, All rights reserved. ========
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #ifndef UTLHASHDICT_H
  7. #define UTLHASHDICT_H
  8. #if defined( _WIN32 )
  9. #pragma once
  10. #endif
  11. #include "tier1/utlhash.h"
  12. #include "tier1/generichash.h"
  13. #include "mathlib/mathlib.h"
  14. //-----------------------------------------------------------------------------
  15. //
  16. //-----------------------------------------------------------------------------
  17. template <typename T, bool bCaseInsensitive = true, bool bDupeStrings = true>
  18. class CUtlHashDict
  19. {
  20. public:
  21. // constructor, destructor
  22. CUtlHashDict( int bucketCount = 16, int growCount = 0, int initCount = 0 );
  23. ~CUtlHashDict( );
  24. // gets particular elements
  25. T& Element( unsigned i );
  26. const T& Element( unsigned i ) const;
  27. T& operator[]( unsigned i );
  28. const T& operator[]( unsigned i ) const;
  29. // gets element names
  30. char const *GetElementName( unsigned i ) const;
  31. // Number of elements
  32. int Count() const;
  33. // Checks if a node is valid and in the tree
  34. bool IsValidIndex( unsigned i ) const;
  35. // Invalid index
  36. static unsigned InvalidHandle();
  37. // Insert method (inserts in order)
  38. unsigned Insert( const char *pName, const T &element );
  39. unsigned Insert( const char *pName );
  40. // Find method
  41. unsigned Find( const char *pName ) const;
  42. // Remove methods
  43. void RemoveAt( unsigned i );
  44. void Remove( const char *pName );
  45. void RemoveAll( );
  46. // Purge memory
  47. void Purge();
  48. void PurgeAndDeleteElements(); // Call delete on each element.
  49. // Iteration methods
  50. unsigned First() const;
  51. unsigned Next( unsigned i ) const;
  52. protected:
  53. struct Entry_t
  54. {
  55. const char *pszSymbol;
  56. T value;
  57. };
  58. template <bool bCaseIgnore>
  59. class CCompare
  60. {
  61. public:
  62. CCompare( int ignored ) {}
  63. bool operator()( const Entry_t &entry1, const Entry_t &entry2 ) const
  64. {
  65. return !( ( bCaseIgnore ) ? stricmp( entry1.pszSymbol, entry2.pszSymbol ) : strcmp( entry1.pszSymbol, entry2.pszSymbol ) );
  66. }
  67. };
  68. template <bool bCaseIgnore>
  69. class CHash
  70. {
  71. public:
  72. CHash( int ignored ) {}
  73. unsigned operator()( const Entry_t &entry ) const
  74. {
  75. return !( ( bCaseIgnore ) ? HashStringCaseless( entry.pszSymbol ) : HashString( entry.pszSymbol ) );
  76. }
  77. };
  78. typedef CUtlHash<Entry_t, CCompare<bCaseInsensitive>, CHash<bCaseInsensitive> > CHashTable;
  79. CHashTable m_Elements;
  80. int m_nCount;
  81. };
  82. //-----------------------------------------------------------------------------
  83. // constructor, destructor
  84. //-----------------------------------------------------------------------------
  85. template <typename T, bool bCaseInsensitive, bool bDupeStrings>
  86. CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::CUtlHashDict( int bucketCount = 16, int growCount = 0, int initCount = 0 ) :
  87. m_Elements( SmallestPowerOfTwoGreaterOrEqual(bucketCount), growCount, initCount )
  88. {
  89. Assert( SmallestPowerOfTwoGreaterOrEqual(bucketCount) <= 0xffff );
  90. }
  91. template <typename T, bool bCaseInsensitive, bool bDupeStrings>
  92. CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::~CUtlHashDict()
  93. {
  94. Purge();
  95. }
  96. //-----------------------------------------------------------------------------
  97. // gets particular elements
  98. //-----------------------------------------------------------------------------
  99. template <typename T, bool bCaseInsensitive, bool bDupeStrings>
  100. inline T& CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::Element( unsigned i )
  101. {
  102. return m_Elements[i].value;
  103. }
  104. template <typename T, bool bCaseInsensitive, bool bDupeStrings>
  105. inline const T& CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::Element( unsigned i ) const
  106. {
  107. return m_Elements[i].value;
  108. }
  109. //-----------------------------------------------------------------------------
  110. // gets element names
  111. //-----------------------------------------------------------------------------
  112. template <typename T, bool bCaseInsensitive, bool bDupeStrings>
  113. inline char const *CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::GetElementName( unsigned i ) const
  114. {
  115. return m_Elements[i].pszSymbol;
  116. }
  117. template <typename T, bool bCaseInsensitive, bool bDupeStrings>
  118. inline T& CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::operator[]( unsigned i )
  119. {
  120. return m_Elements[i].value;
  121. }
  122. template <typename T, bool bCaseInsensitive, bool bDupeStrings>
  123. inline const T & CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::operator[]( unsigned i ) const
  124. {
  125. return m_Elements[i].value;
  126. }
  127. //-----------------------------------------------------------------------------
  128. // Num elements
  129. //-----------------------------------------------------------------------------
  130. template <typename T, bool bCaseInsensitive, bool bDupeStrings>
  131. inline int CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::Count() const
  132. {
  133. Assert( m_nCount == m_Elements.Count() );
  134. return m_nCount;
  135. }
  136. //-----------------------------------------------------------------------------
  137. // Checks if a node is valid and in the tree
  138. //-----------------------------------------------------------------------------
  139. template <typename T, bool bCaseInsensitive, bool bDupeStrings>
  140. inline bool CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::IsValidIndex( unsigned i ) const
  141. {
  142. return m_Elements.IsValidHandle(i);
  143. }
  144. //-----------------------------------------------------------------------------
  145. // Invalid index
  146. //-----------------------------------------------------------------------------
  147. template <typename T, bool bCaseInsensitive, bool bDupeStrings>
  148. inline unsigned CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::InvalidHandle()
  149. {
  150. return CHashTable::InvalidHandle();
  151. }
  152. //-----------------------------------------------------------------------------
  153. // Delete a node from the tree
  154. //-----------------------------------------------------------------------------
  155. template <typename T, bool bCaseInsensitive, bool bDupeStrings>
  156. void CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::RemoveAt(unsigned elem)
  157. {
  158. if ( bDupeStrings )
  159. {
  160. free( (void *)m_Elements[elem].pszSymbol );
  161. }
  162. m_Elements.Remove(elem);
  163. m_nCount--;
  164. }
  165. //-----------------------------------------------------------------------------
  166. // remove a node in the tree
  167. //-----------------------------------------------------------------------------
  168. template <typename T, bool bCaseInsensitive, bool bDupeStrings> void CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::Remove( const char *search )
  169. {
  170. unsigned node = Find( search );
  171. if (node != InvalidHandle())
  172. {
  173. RemoveAt(node);
  174. }
  175. }
  176. //-----------------------------------------------------------------------------
  177. // Removes all nodes from the tree
  178. //-----------------------------------------------------------------------------
  179. template <typename T, bool bCaseInsensitive, bool bDupeStrings>
  180. void CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::RemoveAll()
  181. {
  182. if ( bDupeStrings )
  183. {
  184. UtlHashHandle_t index = m_Elements.GetFirstHandle();
  185. while ( index != m_Elements.InvalidHandle() )
  186. {
  187. free( (void *)m_Elements[index].pszSymbol );
  188. index = m_Elements.GetNextHandle( index );
  189. }
  190. }
  191. m_Elements.RemoveAll();
  192. m_nCount = 0;
  193. }
  194. template <typename T, bool bCaseInsensitive, bool bDupeStrings>
  195. void CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::Purge()
  196. {
  197. if ( bDupeStrings )
  198. {
  199. UtlHashHandle_t index = m_Elements.GetFirstHandle();
  200. while ( index != m_Elements.InvalidHandle() )
  201. {
  202. free( (void *)m_Elements[index].pszSymbol );
  203. index = m_Elements.GetNextHandle( index );
  204. }
  205. }
  206. m_Elements.Purge();
  207. m_nCount = 0;
  208. }
  209. template <typename T, bool bCaseInsensitive, bool bDupeStrings>
  210. void CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::PurgeAndDeleteElements()
  211. {
  212. // Delete all the elements.
  213. unsigned index = m_Elements.GetFirstHandle();
  214. while ( index != m_Elements.InvalidHandle() )
  215. {
  216. if ( bDupeStrings )
  217. {
  218. free( (void *)m_Elements[index].pszSymbol );
  219. }
  220. delete m_Elements[index].value;
  221. index = m_Elements.GetNextHandle( index );
  222. }
  223. m_Elements.RemoveAll();
  224. m_nCount = 0;
  225. }
  226. //-----------------------------------------------------------------------------
  227. // inserts a node into the tree
  228. //-----------------------------------------------------------------------------
  229. template <typename T, bool bCaseInsensitive, bool bDupeStrings>
  230. unsigned CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::Insert( const char *pName, const T &element )
  231. {
  232. MEM_ALLOC_CREDIT_CLASS();
  233. m_nCount++;
  234. Entry_t entry =
  235. {
  236. (bDupeStrings) ? strdup( pName ) : pName,
  237. element
  238. };
  239. bool bInserted;
  240. unsigned result = m_Elements.Insert( entry, &bInserted );
  241. if ( bDupeStrings && !bInserted )
  242. {
  243. free( (void *)entry.pszSymbol );
  244. }
  245. return result;
  246. }
  247. template <typename T, bool bCaseInsensitive, bool bDupeStrings>
  248. unsigned CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::Insert( const char *pName )
  249. {
  250. MEM_ALLOC_CREDIT_CLASS();
  251. m_nCount++;
  252. Entry_t entry =
  253. {
  254. (bDupeStrings) ? strdup( pName ) : pName
  255. };
  256. bool bInserted;
  257. unsigned result = m_Elements.Insert( entry, &bInserted );
  258. if ( bDupeStrings && !bInserted )
  259. {
  260. free( (void *)entry.pszSymbol );
  261. }
  262. return result;
  263. }
  264. //-----------------------------------------------------------------------------
  265. // finds a node in the tree
  266. //-----------------------------------------------------------------------------
  267. template <typename T, bool bCaseInsensitive, bool bDupeStrings>
  268. unsigned CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::Find( const char *pName ) const
  269. {
  270. MEM_ALLOC_CREDIT_CLASS();
  271. if ( pName )
  272. return m_Elements.Find( *((Entry_t *)&pName) );
  273. else
  274. return InvalidHandle();
  275. }
  276. //-----------------------------------------------------------------------------
  277. // Iteration methods
  278. //-----------------------------------------------------------------------------
  279. template <typename T, bool bCaseInsensitive, bool bDupeStrings>
  280. unsigned CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::First() const
  281. {
  282. return m_Elements.GetFirstHandle();
  283. }
  284. template <typename T, bool bCaseInsensitive, bool bDupeStrings>
  285. unsigned CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::Next( unsigned i ) const
  286. {
  287. return m_Elements.GetNextHandle(i);
  288. }
  289. #endif // UTLHASHDICT_H