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.

211 lines
6.6 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose: Special case hash table for console commands
  4. //
  5. // $NoKeywords: $
  6. //
  7. //===========================================================================//
  8. #if !defined( CONCOMMANDHASH_H )
  9. #define CONCOMMANDHASH_H
  10. #ifdef _WIN32
  11. #pragma once
  12. #endif
  13. #include "utllinkedlist.h"
  14. #include "generichash.h"
  15. // This is a hash table class very similar to the CUtlHashFast, but
  16. // modified specifically so that we can look up ConCommandBases
  17. // by string names without having to actually store those strings in
  18. // the dictionary, and also iterate over all of them.
  19. // It uses separate chaining: each key hashes to a bucket, each
  20. // bucket is a linked list of hashed commands. We store the hash of
  21. // the command's string name as well as its pointer, so we can do
  22. // the linked list march part of the Find() operation more quickly.
  23. class CConCommandHash
  24. {
  25. public:
  26. typedef intp CCommandHashHandle_t;
  27. typedef unsigned int HashKey_t;
  28. // Constructor/Deconstructor.
  29. CConCommandHash();
  30. ~CConCommandHash();
  31. // Memory.
  32. void Purge( bool bReinitialize );
  33. // Invalid handle.
  34. static CCommandHashHandle_t InvalidHandle( void ) { return ( CCommandHashHandle_t )~0; }
  35. inline bool IsValidHandle( CCommandHashHandle_t hHash ) const;
  36. /// Initialize.
  37. void Init( void ); // bucket count is hardcoded in enum below.
  38. /// Get hash value for a concommand
  39. static inline HashKey_t Hash( const ConCommandBase *cmd );
  40. // Size not available; count is meaningless for multilists.
  41. // int Count( void ) const;
  42. // Insertion.
  43. CCommandHashHandle_t Insert( ConCommandBase *cmd );
  44. CCommandHashHandle_t FastInsert( ConCommandBase *cmd );
  45. // Removal.
  46. void Remove( CCommandHashHandle_t hHash ) RESTRICT;
  47. void RemoveAll( void );
  48. // Retrieval.
  49. inline CCommandHashHandle_t Find( const char *name ) const;
  50. CCommandHashHandle_t Find( const ConCommandBase *cmd ) const RESTRICT;
  51. // A convenience version of Find that skips the handle part
  52. // and returns a pointer to a concommand, or NULL if none was found.
  53. inline ConCommandBase * FindPtr( const char *name ) const;
  54. inline ConCommandBase * &operator[]( CCommandHashHandle_t hHash );
  55. inline ConCommandBase *const &operator[]( CCommandHashHandle_t hHash ) const;
  56. #ifdef _DEBUG
  57. // Dump a report to MSG
  58. void Report( void );
  59. #endif
  60. // Iteration
  61. struct CCommandHashIterator_t
  62. {
  63. int bucket;
  64. CCommandHashHandle_t handle;
  65. CCommandHashIterator_t(int _bucket, const CCommandHashHandle_t &_handle)
  66. : bucket(_bucket), handle(_handle) {};
  67. // inline operator UtlHashFastHandle_t() const { return handle; };
  68. };
  69. inline CCommandHashIterator_t First() const;
  70. inline CCommandHashIterator_t Next( const CCommandHashIterator_t &hHash ) const;
  71. inline bool IsValidIterator( const CCommandHashIterator_t &iter ) const;
  72. inline ConCommandBase * &operator[]( const CCommandHashIterator_t &iter ) { return (*this)[iter.handle]; }
  73. inline ConCommandBase * const &operator[]( const CCommandHashIterator_t &iter ) const { return (*this)[iter.handle]; }
  74. private:
  75. // a find func where we've already computed the hash for the string.
  76. // (hidden private in case we decide to invent a custom string hash func
  77. // for this class)
  78. CCommandHashHandle_t Find( const char *name, HashKey_t hash) const RESTRICT;
  79. protected:
  80. enum
  81. {
  82. kNUM_BUCKETS = 256,
  83. kBUCKETMASK = kNUM_BUCKETS - 1,
  84. };
  85. struct HashEntry_t
  86. {
  87. HashKey_t m_uiKey;
  88. ConCommandBase *m_Data;
  89. HashEntry_t(unsigned int _hash, ConCommandBase * _cmd)
  90. : m_uiKey(_hash), m_Data(_cmd) {};
  91. HashEntry_t(){};
  92. };
  93. typedef CUtlFixedLinkedList<HashEntry_t> datapool_t;
  94. CUtlVector<CCommandHashHandle_t> m_aBuckets;
  95. datapool_t m_aDataPool;
  96. };
  97. inline bool CConCommandHash::IsValidHandle( CCommandHashHandle_t hHash ) const
  98. {
  99. return m_aDataPool.IsValidIndex(hHash);
  100. }
  101. inline CConCommandHash::CCommandHashHandle_t CConCommandHash::Find( const char *name ) const
  102. {
  103. return Find( name, HashStringCaseless(name) );
  104. }
  105. inline ConCommandBase * &CConCommandHash::operator[]( CCommandHashHandle_t hHash )
  106. {
  107. return ( m_aDataPool[hHash].m_Data );
  108. }
  109. inline ConCommandBase *const &CConCommandHash::operator[]( CCommandHashHandle_t hHash ) const
  110. {
  111. return ( m_aDataPool[hHash].m_Data );
  112. }
  113. //-----------------------------------------------------------------------------
  114. // Purpose: For iterating over the whole hash, return the index of the first element
  115. //-----------------------------------------------------------------------------
  116. CConCommandHash::CCommandHashIterator_t CConCommandHash::First() const
  117. {
  118. // walk through the buckets to find the first one that has some data
  119. int bucketCount = m_aBuckets.Count();
  120. const CCommandHashHandle_t invalidIndex = m_aDataPool.InvalidIndex();
  121. for ( int bucket = 0 ; bucket < bucketCount ; ++bucket )
  122. {
  123. CCommandHashHandle_t iElement = m_aBuckets[bucket]; // get the head of the bucket
  124. if ( iElement != invalidIndex )
  125. return CCommandHashIterator_t( bucket, iElement );
  126. }
  127. // if we are down here, the list is empty
  128. return CCommandHashIterator_t( -1, invalidIndex );
  129. }
  130. //-----------------------------------------------------------------------------
  131. // Purpose: For iterating over the whole hash, return the next element after
  132. // the param one. Or an invalid iterator.
  133. //-----------------------------------------------------------------------------
  134. CConCommandHash::CCommandHashIterator_t
  135. CConCommandHash::Next( const CConCommandHash::CCommandHashIterator_t &iter ) const
  136. {
  137. // look for the next entry in the current bucket
  138. CCommandHashHandle_t next = m_aDataPool.Next(iter.handle);
  139. const CCommandHashHandle_t invalidIndex = m_aDataPool.InvalidIndex();
  140. if ( next != invalidIndex )
  141. {
  142. // this bucket still has more elements in it
  143. return CCommandHashIterator_t(iter.bucket, next);
  144. }
  145. // otherwise look for the next bucket with data
  146. int bucketCount = m_aBuckets.Count();
  147. for ( int bucket = iter.bucket+1 ; bucket < bucketCount ; ++bucket )
  148. {
  149. CCommandHashHandle_t next = m_aBuckets[bucket]; // get the head of the bucket
  150. if (next != invalidIndex)
  151. return CCommandHashIterator_t( bucket, next );
  152. }
  153. // if we're here, there's no more data to be had
  154. return CCommandHashIterator_t(-1, invalidIndex);
  155. }
  156. bool CConCommandHash::IsValidIterator( const CCommandHashIterator_t &iter ) const
  157. {
  158. return ( (iter.bucket >= 0) && (m_aDataPool.IsValidIndex(iter.handle)) );
  159. }
  160. inline CConCommandHash::HashKey_t CConCommandHash::Hash( const ConCommandBase *cmd )
  161. {
  162. return HashStringCaseless( cmd->GetName() );
  163. }
  164. inline ConCommandBase * CConCommandHash::FindPtr( const char *name ) const
  165. {
  166. CCommandHashHandle_t handle = Find(name);
  167. if (handle == InvalidHandle())
  168. {
  169. return NULL;
  170. }
  171. else
  172. {
  173. return (*this)[handle];
  174. }
  175. }
  176. #endif