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.

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