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.

380 lines
11 KiB

  1. //===== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose: Defines a symbol table
  4. //
  5. // $Header: $
  6. // $NoKeywords: $
  7. //===========================================================================//
  8. #ifndef UTLSYMBOL_H
  9. #define UTLSYMBOL_H
  10. #ifdef _WIN32
  11. #pragma once
  12. #endif
  13. #include "tier0/platform.h"
  14. #include "tier0/threadtools.h"
  15. #include "tier1/utlrbtree.h"
  16. #include "tier1/utlvector.h"
  17. #include "tier1/utlbuffer.h"
  18. #include "tier1/utllinkedlist.h"
  19. #include "tier1/stringpool.h"
  20. //-----------------------------------------------------------------------------
  21. // forward declarations
  22. //-----------------------------------------------------------------------------
  23. class CUtlSymbolTable;
  24. class CUtlSymbolTableMT;
  25. //-----------------------------------------------------------------------------
  26. // This is a symbol, which is a easier way of dealing with strings.
  27. //-----------------------------------------------------------------------------
  28. typedef unsigned short UtlSymId_t;
  29. #define UTL_INVAL_SYMBOL ((UtlSymId_t)~0)
  30. class CUtlSymbol
  31. {
  32. public:
  33. // constructor, destructor
  34. CUtlSymbol() : m_Id(UTL_INVAL_SYMBOL) {}
  35. CUtlSymbol( UtlSymId_t id ) : m_Id(id) {}
  36. CUtlSymbol( const char* pStr );
  37. CUtlSymbol( CUtlSymbol const& sym ) : m_Id(sym.m_Id) {}
  38. // operator=
  39. CUtlSymbol& operator=( CUtlSymbol const& src ) { m_Id = src.m_Id; return *this; }
  40. // operator==
  41. bool operator==( CUtlSymbol const& src ) const { return m_Id == src.m_Id; }
  42. bool operator==( const char* pStr ) const;
  43. // Is valid?
  44. bool IsValid() const { return m_Id != UTL_INVAL_SYMBOL; }
  45. // Gets at the symbol
  46. operator UtlSymId_t () const { return m_Id; }
  47. // Gets the string associated with the symbol
  48. const char* String( ) const;
  49. // Modules can choose to disable the static symbol table so to prevent accidental use of them.
  50. static void DisableStaticSymbolTable();
  51. // Methods with explicit locking mechanism. Only use for optimization reasons.
  52. static void LockTableForRead();
  53. static void UnlockTableForRead();
  54. const char * StringNoLock() const;
  55. protected:
  56. UtlSymId_t m_Id;
  57. // Initializes the symbol table
  58. static void Initialize();
  59. // returns the current symbol table
  60. static CUtlSymbolTableMT* CurrTable();
  61. // The standard global symbol table
  62. static CUtlSymbolTableMT* s_pSymbolTable;
  63. static bool s_bAllowStaticSymbolTable;
  64. friend class CCleanupUtlSymbolTable;
  65. };
  66. //-----------------------------------------------------------------------------
  67. // CUtlSymbolTable:
  68. // description:
  69. // This class defines a symbol table, which allows us to perform mappings
  70. // of strings to symbols and back. The symbol class itself contains
  71. // a static version of this class for creating global strings, but this
  72. // class can also be instanced to create local symbol tables.
  73. //
  74. // This class stores the strings in a series of string pools. The first
  75. // two bytes of each string are decorated with a hash to speed up
  76. // comparisons.
  77. //-----------------------------------------------------------------------------
  78. class CUtlSymbolTable
  79. {
  80. public:
  81. // constructor, destructor
  82. CUtlSymbolTable( int growSize = 0, int initSize = 16, bool caseInsensitive = false );
  83. ~CUtlSymbolTable();
  84. // Finds and/or creates a symbol based on the string
  85. CUtlSymbol AddString( const char* pString );
  86. // Finds the symbol for pString
  87. CUtlSymbol Find( const char* pString ) const;
  88. // Look up the string associated with a particular symbol
  89. const char* String( CUtlSymbol id ) const;
  90. inline bool HasElement(const char* pStr) const
  91. {
  92. return Find(pStr) != UTL_INVAL_SYMBOL;
  93. }
  94. // Remove all symbols in the table.
  95. void RemoveAll();
  96. int GetNumStrings( void ) const
  97. {
  98. return m_Lookup.Count();
  99. }
  100. // We store one of these at the beginning of every string to speed
  101. // up comparisons.
  102. typedef unsigned short hashDecoration_t;
  103. protected:
  104. class CStringPoolIndex
  105. {
  106. public:
  107. inline CStringPoolIndex()
  108. {
  109. }
  110. inline CStringPoolIndex( unsigned short iPool, unsigned short iOffset )
  111. : m_iPool(iPool), m_iOffset(iOffset)
  112. {}
  113. inline bool operator==( const CStringPoolIndex &other ) const
  114. {
  115. return m_iPool == other.m_iPool && m_iOffset == other.m_iOffset;
  116. }
  117. unsigned short m_iPool; // Index into m_StringPools.
  118. unsigned short m_iOffset; // Index into the string pool.
  119. };
  120. class CLess
  121. {
  122. public:
  123. CLess( int ignored = 0 ) {} // permits default initialization to NULL in CUtlRBTree
  124. bool operator!() const { return false; }
  125. bool operator()( const CStringPoolIndex &left, const CStringPoolIndex &right ) const;
  126. };
  127. // Stores the symbol lookup
  128. class CTree : public CUtlRBTree<CStringPoolIndex, unsigned short, CLess>
  129. {
  130. public:
  131. CTree( int growSize, int initSize ) : CUtlRBTree<CStringPoolIndex, unsigned short, CLess>( growSize, initSize ) {}
  132. friend class CUtlSymbolTable::CLess; // Needed to allow CLess to calculate pointer to symbol table
  133. };
  134. struct StringPool_t
  135. {
  136. int m_TotalLen; // How large is
  137. int m_SpaceUsed;
  138. char m_Data[1];
  139. };
  140. CTree m_Lookup;
  141. bool m_bInsensitive;
  142. mutable unsigned short m_nUserSearchStringHash;
  143. mutable const char* m_pUserSearchString;
  144. // stores the string data
  145. CUtlVector<StringPool_t*> m_StringPools;
  146. private:
  147. int FindPoolWithSpace( int len ) const;
  148. const char* StringFromIndex( const CStringPoolIndex &index ) const;
  149. const char* DecoratedStringFromIndex( const CStringPoolIndex &index ) const;
  150. friend class CLess;
  151. friend class CSymbolHash;
  152. };
  153. class CUtlSymbolTableMT : public CUtlSymbolTable
  154. {
  155. public:
  156. CUtlSymbolTableMT( int growSize = 0, int initSize = 32, bool caseInsensitive = false )
  157. : CUtlSymbolTable( growSize, initSize, caseInsensitive )
  158. {
  159. }
  160. CUtlSymbol AddString( const char* pString )
  161. {
  162. m_lock.LockForWrite();
  163. CUtlSymbol result = CUtlSymbolTable::AddString( pString );
  164. m_lock.UnlockWrite();
  165. return result;
  166. }
  167. CUtlSymbol Find( const char* pString ) const
  168. {
  169. m_lock.LockForWrite();
  170. CUtlSymbol result = CUtlSymbolTable::Find( pString );
  171. m_lock.UnlockWrite();
  172. return result;
  173. }
  174. const char* String( CUtlSymbol id ) const
  175. {
  176. m_lock.LockForRead();
  177. const char *pszResult = CUtlSymbolTable::String( id );
  178. m_lock.UnlockRead();
  179. return pszResult;
  180. }
  181. const char * StringNoLock( CUtlSymbol id ) const
  182. {
  183. return CUtlSymbolTable::String( id );
  184. }
  185. void LockForRead()
  186. {
  187. m_lock.LockForRead();
  188. }
  189. void UnlockForRead()
  190. {
  191. m_lock.UnlockRead();
  192. }
  193. private:
  194. #ifdef WIN32
  195. mutable CThreadSpinRWLock m_lock;
  196. #else
  197. mutable CThreadRWLock m_lock;
  198. #endif
  199. };
  200. //-----------------------------------------------------------------------------
  201. // CUtlFilenameSymbolTable:
  202. // description:
  203. // This class defines a symbol table of individual filenames, stored more
  204. // efficiently than a standard symbol table. Internally filenames are broken
  205. // up into file and path entries, and a file handle class allows convenient
  206. // access to these.
  207. //-----------------------------------------------------------------------------
  208. // The handle is a CUtlSymbol for the dirname and the same for the filename, the accessor
  209. // copies them into a static char buffer for return.
  210. typedef void* FileNameHandle_t;
  211. // Symbol table for more efficiently storing filenames by breaking paths and filenames apart.
  212. // Refactored from BaseFileSystem.h
  213. class CUtlFilenameSymbolTable
  214. {
  215. // Internal representation of a FileHandle_t
  216. // If we get more than 64K filenames, we'll have to revisit...
  217. // Right now CUtlSymbol is a short, so this packs into an int/void * pointer size...
  218. struct FileNameHandleInternal_t
  219. {
  220. FileNameHandleInternal_t()
  221. {
  222. COMPILE_TIME_ASSERT( sizeof( *this ) == sizeof( FileNameHandle_t ) );
  223. COMPILE_TIME_ASSERT( sizeof( value ) == 4 );
  224. value = 0;
  225. #ifdef PLATFORM_64BITS
  226. pad = 0;
  227. #endif
  228. }
  229. // We pack the path and file values into a single 32 bit value. We were running
  230. // out of space with the two 16 bit values (more than 64k files) so instead of increasing
  231. // the total size we split the underlying pool into two (paths and files) and
  232. // use a smaller path string pool and a larger file string pool.
  233. unsigned int value;
  234. #ifdef PLATFORM_64BITS
  235. // some padding to make sure we are the same size as FileNameHandle_t on 64 bit.
  236. unsigned int pad;
  237. #endif
  238. static const unsigned int cNumBitsInPath = 12;
  239. static const unsigned int cNumBitsInFile = 32 - cNumBitsInPath;
  240. static const unsigned int cMaxPathValue = 1 << cNumBitsInPath;
  241. static const unsigned int cMaxFileValue = 1 << cNumBitsInFile;
  242. static const unsigned int cPathBitMask = cMaxPathValue - 1;
  243. static const unsigned int cFileBitMask = cMaxFileValue - 1;
  244. // Part before the final '/' character
  245. unsigned int GetPath() const { return ((value >> cNumBitsInFile) & cPathBitMask); }
  246. void SetPath( unsigned int path ) { Assert( path < cMaxPathValue ); value = ((value & cFileBitMask) | ((path & cPathBitMask) << cNumBitsInFile)); }
  247. // Part after the final '/', including extension
  248. unsigned int GetFile() const { return (value & cFileBitMask); }
  249. void SetFile( unsigned int file ) { Assert( file < cMaxFileValue ); value = ((value & (cPathBitMask << cNumBitsInFile)) | (file & cFileBitMask)); }
  250. };
  251. public:
  252. FileNameHandle_t FindOrAddFileName( const char *pFileName );
  253. FileNameHandle_t FindFileName( const char *pFileName );
  254. int PathIndex( const FileNameHandle_t &handle ) { return (( const FileNameHandleInternal_t * )&handle)->GetPath(); }
  255. bool String( const FileNameHandle_t& handle, char *buf, int buflen );
  256. void RemoveAll();
  257. void SpewStrings();
  258. bool SaveToBuffer( CUtlBuffer &buffer );
  259. bool RestoreFromBuffer( CUtlBuffer &buffer );
  260. private:
  261. CCountedStringPoolBase<unsigned short> m_PathStringPool;
  262. CCountedStringPoolBase<unsigned int> m_FileStringPool;
  263. mutable CThreadSpinRWLock m_lock;
  264. };
  265. // This creates a simple class that includes the underlying CUtlSymbol
  266. // as a private member and then instances a private symbol table to
  267. // manage those symbols. Avoids the possibility of the code polluting the
  268. // 'global'/default symbol table, while letting the code look like
  269. // it's just using = and .String() to look at CUtlSymbol type objects
  270. //
  271. // NOTE: You can't pass these objects between .dlls in an interface (also true of CUtlSymbol of course)
  272. //
  273. #define DECLARE_PRIVATE_SYMBOLTYPE( typename ) \
  274. class typename \
  275. { \
  276. public: \
  277. typename(); \
  278. typename( const char* pStr ); \
  279. typename& operator=( typename const& src ); \
  280. bool operator==( typename const& src ) const; \
  281. const char* String( ) const; \
  282. private: \
  283. CUtlSymbol m_SymbolId; \
  284. };
  285. // Put this in the .cpp file that uses the above typename
  286. #define IMPLEMENT_PRIVATE_SYMBOLTYPE( typename ) \
  287. static CUtlSymbolTable g_##typename##SymbolTable; \
  288. typename::typename() \
  289. { \
  290. m_SymbolId = UTL_INVAL_SYMBOL; \
  291. } \
  292. typename::typename( const char* pStr ) \
  293. { \
  294. m_SymbolId = g_##typename##SymbolTable.AddString( pStr ); \
  295. } \
  296. typename& typename::operator=( typename const& src ) \
  297. { \
  298. m_SymbolId = src.m_SymbolId; \
  299. return *this; \
  300. } \
  301. bool typename::operator==( typename const& src ) const \
  302. { \
  303. return ( m_SymbolId == src.m_SymbolId ); \
  304. } \
  305. const char* typename::String( ) const \
  306. { \
  307. return g_##typename##SymbolTable.String( m_SymbolId ); \
  308. }
  309. #endif // UTLSYMBOL_H