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.

385 lines
16 KiB

  1. //========= Copyright � 2011, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: common helpers for reuse among various Utl containers
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #ifndef UTLCOMMON_H
  9. #define UTLCOMMON_H
  10. #pragma once
  11. #include "strtools.h"
  12. //-----------------------------------------------------------------------------
  13. // Henry Goffin (henryg) was here. Questions? Bugs? Go slap him around a bit.
  14. //-----------------------------------------------------------------------------
  15. // empty_t is the canonical "no-value" type which is fully defined but empty.
  16. struct empty_t {};
  17. // undefined_t is the canonical "undefined" type, used mostly for typedefs;
  18. // parameters of type undefined_t will not compile, which is actually useful
  19. // behavior when it comes to template programming. Google "SFINAE" for info.
  20. struct undefined_t;
  21. // CTypeSelect<sel,A,B>::type is a typedef of A if sel is nonzero, else B
  22. template <int sel, typename A, typename B>
  23. struct CTypeSelect { typedef A type; };
  24. template <typename A, typename B>
  25. struct CTypeSelect<0, A, B> { typedef B type; };
  26. // CTypeEquals<A, B>::value is nonzero if A and B are the same type
  27. template <typename A, typename B, bool bIgnoreConstVolatile = false, bool bIgnoreReference = false>
  28. struct CTypeEquals { enum { value = 0 }; };
  29. template <typename Same>
  30. struct CTypeEquals<Same, Same, false, false> { enum { value = 1 }; };
  31. template <typename A, typename B>
  32. struct CTypeEquals<A, B, true, true> : CTypeEquals< const volatile A&, const volatile B& > {};
  33. template <typename A, typename B>
  34. struct CTypeEquals<A, B, true, false> : CTypeEquals< const volatile A, const volatile B > {};
  35. template <typename A, typename B>
  36. struct CTypeEquals<A, B, false, true> : CTypeEquals< A&, B& > {};
  37. // CUtlKeyValuePair is intended for use with key-lookup containers.
  38. // Because it is specialized for "empty_t" values, one container can
  39. // function as either a set of keys OR a key-value dictionary while
  40. // avoiding storage waste or padding for the empty_t value objects.
  41. template <typename K, typename V>
  42. class CUtlKeyValuePair
  43. {
  44. public:
  45. typedef V ValueReturn_t;
  46. K m_key;
  47. V m_value;
  48. CUtlKeyValuePair() {}
  49. template < typename KInit >
  50. explicit CUtlKeyValuePair( const KInit &k ) : m_key( k ) {}
  51. template < typename KInit, typename VInit >
  52. CUtlKeyValuePair( const KInit &k, const VInit &v ) : m_key( k ), m_value( v ) {}
  53. V &GetValue() { return m_value; }
  54. const V &GetValue() const { return m_value; }
  55. };
  56. template <typename K>
  57. class CUtlKeyValuePair<K, empty_t>
  58. {
  59. public:
  60. typedef const K ValueReturn_t;
  61. K m_key;
  62. CUtlKeyValuePair() {}
  63. template < typename KInit >
  64. explicit CUtlKeyValuePair( const KInit &k ) : m_key( k ) {}
  65. template < typename KInit >
  66. CUtlKeyValuePair( const KInit &k, empty_t ) : m_key( k ) {}
  67. CUtlKeyValuePair( const K &k, const empty_t& ) : m_key( k ) {}
  68. const K &GetValue() const { return m_key; }
  69. };
  70. // Default functors. You can specialize these if your type does
  71. // not implement operator== or operator< in an efficient way for
  72. // some odd reason.
  73. template <typename T> struct DefaultLessFunctor;
  74. template <typename T> struct DefaultEqualFunctor;
  75. // Hashing functor used by hash tables. You can either specialize
  76. // for types which are widely used, or plug a custom functor directly
  77. // into the hash table. If you do roll your own, please read up on
  78. // bit-mixing and the avalanche property; be sure that your values
  79. // are reasonably well-distributed across the entire 32-bit range.
  80. // http://en.wikipedia.org/wiki/Avalanche_effect
  81. // http://home.comcast.net/~bretm/hash/5.html
  82. //
  83. template <typename T> struct DefaultHashFunctor;
  84. // Argument type information. Struct currently contains one or two typedefs:
  85. // typename Arg_t = primary argument type. Usually const T&, sometimes T.
  86. // typename Alt_t = optional alternate type. Usually *undefined*.
  87. //
  88. // Any specializations should be implemented via simple inheritance
  89. // from ArgumentTypeInfoImpl< BestArgType, [optional] AlternateArgType >
  90. //
  91. template <typename T> struct ArgumentTypeInfo;
  92. // Some fundamental building-block functors...
  93. struct StringLessFunctor
  94. {
  95. StringLessFunctor( int i ) {};
  96. StringLessFunctor( void ) {};
  97. inline bool operator!() const { return false; }
  98. bool operator()( const char *a, const char *b ) const
  99. {
  100. return V_strcmp( a, b ) < 0;
  101. }
  102. };
  103. struct StringEqualFunctor { bool operator()( const char *a, const char *b ) const { return V_strcmp( a, b ) == 0; } };
  104. struct CaselessStringLessFunctor { bool operator()( const char *a, const char *b ) const { return V_strcasecmp( a, b ) < 0; } };
  105. struct CaselessStringEqualFunctor { bool operator()( const char *a, const char *b ) const { return V_strcasecmp( a, b ) == 0; } };
  106. struct IdentityHashFunctor { unsigned int operator() ( uint32 s ) const { return s; } };
  107. struct Mix32HashFunctor { unsigned int operator()( uint32 s ) const; };
  108. struct Mix64HashFunctor { unsigned int operator()( uint64 s ) const; };
  109. struct StringHashFunctor { unsigned int operator()( const char* s ) const; };
  110. struct CaselessStringHashFunctor { unsigned int operator()( const char* s ) const; };
  111. struct PointerLessFunctor { bool operator()( const void *a, const void *b ) const { return a < b; } };
  112. struct PointerEqualFunctor { bool operator()( const void *a, const void *b ) const { return a == b; } };
  113. #if defined( PLATFORM_64BITS )
  114. struct PointerHashFunctor { unsigned int operator()( const void* s ) const { return Mix64HashFunctor()( ( uintp ) s ); } };
  115. #else
  116. struct PointerHashFunctor { unsigned int operator()( const void* s ) const { return Mix32HashFunctor()( ( uintp ) s ); } };
  117. #endif
  118. // Generic implementation of Less and Equal functors
  119. template < typename T >
  120. struct DefaultLessFunctor
  121. {
  122. bool operator()( typename ArgumentTypeInfo< T >::Arg_t a, typename ArgumentTypeInfo< T >::Arg_t b ) const { return a < b; }
  123. bool operator()( typename ArgumentTypeInfo< T >::Alt_t a, typename ArgumentTypeInfo< T >::Arg_t b ) const { return a < b; }
  124. bool operator()( typename ArgumentTypeInfo< T >::Arg_t a, typename ArgumentTypeInfo< T >::Alt_t b ) const { return a < b; }
  125. };
  126. template < typename T >
  127. struct DefaultEqualFunctor
  128. {
  129. bool operator()( typename ArgumentTypeInfo< T >::Arg_t a, typename ArgumentTypeInfo< T >::Arg_t b ) const { return a == b; }
  130. bool operator()( typename ArgumentTypeInfo< T >::Alt_t a, typename ArgumentTypeInfo< T >::Arg_t b ) const { return a == b; }
  131. bool operator()( typename ArgumentTypeInfo< T >::Arg_t a, typename ArgumentTypeInfo< T >::Alt_t b ) const { return a == b; }
  132. };
  133. // Hashes for basic types
  134. template <> struct DefaultHashFunctor<char> : Mix32HashFunctor { };
  135. template <> struct DefaultHashFunctor<signed char> : Mix32HashFunctor { };
  136. template <> struct DefaultHashFunctor<unsigned char> : Mix32HashFunctor { };
  137. template <> struct DefaultHashFunctor<signed short> : Mix32HashFunctor { };
  138. template <> struct DefaultHashFunctor<unsigned short> : Mix32HashFunctor { };
  139. template <> struct DefaultHashFunctor<signed int> : Mix32HashFunctor { };
  140. template <> struct DefaultHashFunctor<unsigned int> : Mix32HashFunctor { };
  141. #if !defined(PLATFORM_64BITS) || defined(_WIN32)
  142. template <> struct DefaultHashFunctor<signed long> : Mix32HashFunctor { };
  143. template <> struct DefaultHashFunctor<unsigned long> : Mix32HashFunctor { };
  144. #elif defined(POSIX)
  145. template <> struct DefaultHashFunctor<signed long> : Mix64HashFunctor { };
  146. template <> struct DefaultHashFunctor<unsigned long> : Mix64HashFunctor { };
  147. #endif
  148. template <> struct DefaultHashFunctor<signed long long> : Mix64HashFunctor { };
  149. template <> struct DefaultHashFunctor<unsigned long long> : Mix64HashFunctor { };
  150. template <> struct DefaultHashFunctor<void*> : PointerHashFunctor { };
  151. template <> struct DefaultHashFunctor<const void*> : PointerHashFunctor { };
  152. #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
  153. template <> struct DefaultHashFunctor<wchar_t> : Mix32HashFunctor { };
  154. #endif
  155. // String specializations. If you want to operate on raw values, use
  156. // PointerLessFunctor and friends from the "building-block" section above
  157. template <> struct DefaultLessFunctor<char*> : StringLessFunctor { };
  158. template <> struct DefaultLessFunctor<const char*> : StringLessFunctor { };
  159. template <> struct DefaultEqualFunctor<char*> : StringEqualFunctor { };
  160. template <> struct DefaultEqualFunctor<const char*> : StringEqualFunctor { };
  161. template <> struct DefaultHashFunctor<char*> : StringHashFunctor { };
  162. template <> struct DefaultHashFunctor<const char*> : StringHashFunctor { };
  163. // CUtlString/CUtlConstString are specialized here and not in utlstring.h
  164. // because I consider string datatypes to be fundamental, and don't feel
  165. // comfortable making that header file dependent on this one. (henryg)
  166. class CUtlString;
  167. template < typename T > class CUtlConstStringBase;
  168. template <> struct DefaultLessFunctor<CUtlString> : StringLessFunctor { };
  169. template <> struct DefaultHashFunctor<CUtlString> : StringHashFunctor { };
  170. template <> struct DefaultEqualFunctor<CUtlString> : StringEqualFunctor {};
  171. template < typename T > struct DefaultLessFunctor< CUtlConstStringBase<T> > : StringLessFunctor { };
  172. template < typename T > struct DefaultHashFunctor< CUtlConstStringBase<T> > : StringHashFunctor { };
  173. // Helpers to deduce if a type defines a public AltArgumentType_t typedef:
  174. template < typename T >
  175. struct HasClassAltArgumentType
  176. {
  177. template < typename X > static long Test( typename X::AltArgumentType_t* );
  178. template < typename X > static char Test( ... );
  179. enum { value = ( sizeof( Test< T >( NULL ) ) != sizeof( char ) ) };
  180. };
  181. template < typename T, bool = HasClassAltArgumentType< T >::value >
  182. struct GetClassAltArgumentType { typedef typename T::AltArgumentType_t Result_t; };
  183. template < typename T >
  184. struct GetClassAltArgumentType< T, false > { typedef undefined_t Result_t; };
  185. // Unwrap references; reference types don't have member typedefs.
  186. template < typename T >
  187. struct GetClassAltArgumentType< T&, false > : GetClassAltArgumentType< T > { };
  188. // ArgumentTypeInfoImpl is the base for all ArgumentTypeInfo specializations.
  189. template < typename ArgT, typename AltT = typename GetClassAltArgumentType<ArgT>::Result_t >
  190. struct ArgumentTypeInfoImpl
  191. {
  192. enum { has_alt = 1 };
  193. typedef ArgT Arg_t;
  194. typedef AltT Alt_t;
  195. };
  196. // Handle cases where AltArgumentType_t is typedef'd to undefined_t
  197. template < typename ArgT >
  198. struct ArgumentTypeInfoImpl< ArgT, undefined_t >
  199. {
  200. enum { has_alt = 0 };
  201. typedef ArgT Arg_t;
  202. typedef undefined_t Alt_t;
  203. };
  204. // Handle cases where AltArgumentType_t is typedef'd to the primary type
  205. template < typename ArgT >
  206. struct ArgumentTypeInfoImpl< ArgT, ArgT >
  207. {
  208. enum { has_alt = 0 };
  209. typedef ArgT Arg_t;
  210. typedef undefined_t Alt_t;
  211. };
  212. // By default, everything is passed via const ref and doesn't define an alternate type.
  213. template <typename T> struct ArgumentTypeInfo : ArgumentTypeInfoImpl< const T& > { };
  214. // Small native types are most efficiently passed by value.
  215. template <> struct ArgumentTypeInfo< bool > : ArgumentTypeInfoImpl< bool > { };
  216. template <> struct ArgumentTypeInfo< char > : ArgumentTypeInfoImpl< char > { };
  217. template <> struct ArgumentTypeInfo< signed char > : ArgumentTypeInfoImpl< signed char > { };
  218. template <> struct ArgumentTypeInfo< unsigned char > : ArgumentTypeInfoImpl< unsigned char > { };
  219. template <> struct ArgumentTypeInfo< signed short > : ArgumentTypeInfoImpl< signed short > { };
  220. template <> struct ArgumentTypeInfo< unsigned short > : ArgumentTypeInfoImpl< unsigned short > { };
  221. template <> struct ArgumentTypeInfo< signed int > : ArgumentTypeInfoImpl< signed int > { };
  222. template <> struct ArgumentTypeInfo< unsigned int > : ArgumentTypeInfoImpl< unsigned int > { };
  223. template <> struct ArgumentTypeInfo< signed long > : ArgumentTypeInfoImpl< signed long > { };
  224. template <> struct ArgumentTypeInfo< unsigned long > : ArgumentTypeInfoImpl< unsigned long > { };
  225. template <> struct ArgumentTypeInfo< signed long long > : ArgumentTypeInfoImpl< signed long long > { };
  226. template <> struct ArgumentTypeInfo< unsigned long long > : ArgumentTypeInfoImpl< unsigned long long > { };
  227. template <> struct ArgumentTypeInfo< float > : ArgumentTypeInfoImpl< float > { };
  228. template <> struct ArgumentTypeInfo< double > : ArgumentTypeInfoImpl< double > { };
  229. template <> struct ArgumentTypeInfo< long double > : ArgumentTypeInfoImpl< long double > { };
  230. #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
  231. template <> struct ArgumentTypeInfo< wchar_t > : ArgumentTypeInfoImpl< wchar_t > { };
  232. #endif
  233. // Pointers are also most efficiently passed by value.
  234. template < typename T > struct ArgumentTypeInfo< T* > : ArgumentTypeInfoImpl< T* > { };
  235. // Specializations to unwrap const-decorated types and references
  236. template <typename T> struct ArgumentTypeInfo<const T> : ArgumentTypeInfo<T> { };
  237. template <typename T> struct ArgumentTypeInfo<volatile T> : ArgumentTypeInfo<T> { };
  238. template <typename T> struct ArgumentTypeInfo<const volatile T> : ArgumentTypeInfo<T> { };
  239. template <typename T> struct ArgumentTypeInfo<T&> : ArgumentTypeInfo<T> { };
  240. template <typename T> struct DefaultLessFunctor<const T> : DefaultLessFunctor<T> { };
  241. template <typename T> struct DefaultLessFunctor<volatile T> : DefaultLessFunctor<T> { };
  242. template <typename T> struct DefaultLessFunctor<const volatile T> : DefaultLessFunctor<T> { };
  243. template <typename T> struct DefaultLessFunctor<T&> : DefaultLessFunctor<T> { };
  244. template <typename T> struct DefaultEqualFunctor<const T> : DefaultEqualFunctor<T> { };
  245. template <typename T> struct DefaultEqualFunctor<volatile T> : DefaultEqualFunctor<T> { };
  246. template <typename T> struct DefaultEqualFunctor<const volatile T> : DefaultEqualFunctor<T> { };
  247. template <typename T> struct DefaultEqualFunctor<T&> : DefaultEqualFunctor<T> { };
  248. template <typename T> struct DefaultHashFunctor<const T> : DefaultHashFunctor<T> { };
  249. template <typename T> struct DefaultHashFunctor<volatile T> : DefaultHashFunctor<T> { };
  250. template <typename T> struct DefaultHashFunctor<const volatile T> : DefaultHashFunctor<T> { };
  251. template <typename T> struct DefaultHashFunctor<T&> : DefaultHashFunctor<T> { };
  252. // Hash all pointer types as raw pointers by default
  253. template <typename T> struct DefaultHashFunctor< T * > : PointerHashFunctor { };
  254. // Here follow the useful implementations.
  255. // Bob Jenkins's 32-bit mix function.
  256. inline unsigned int Mix32HashFunctor::operator()( uint32 n ) const
  257. {
  258. // Perform a mixture of the bits in n, where each bit
  259. // of the input value has an equal chance to affect each
  260. // bit of the output. This turns tightly clustered input
  261. // values into a smooth distribution.
  262. //
  263. // This takes 16-20 cycles on modern x86 architectures;
  264. // that's roughly the same cost as a mispredicted branch.
  265. // It's also reasonably efficient on PPC-based consoles.
  266. //
  267. // If you're still thinking, "too many instructions!",
  268. // do keep in mind that reading one byte of uncached RAM
  269. // is about 30x slower than executing this code. It pays
  270. // to have a good hash function which minimizes collisions
  271. // (and therefore long lookup chains).
  272. n = ( n + 0x7ed55d16 ) + ( n << 12 );
  273. n = ( n ^ 0xc761c23c ) ^ ( n >> 19 );
  274. n = ( n + 0x165667b1 ) + ( n << 5 );
  275. n = ( n + 0xd3a2646c ) ^ ( n << 9 );
  276. n = ( n + 0xfd7046c5 ) + ( n << 3 );
  277. n = ( n ^ 0xb55a4f09 ) ^ ( n >> 16 );
  278. return n;
  279. }
  280. inline unsigned int Mix64HashFunctor::operator()( uint64 s ) const
  281. {
  282. // Thomas Wang hash, http://www.concentric.net/~ttwang/tech/inthash.htm
  283. s = ( ~s ) + ( s << 21 ); // s = (s << 21) - s - 1;
  284. s = s ^ ( s >> 24 );
  285. s = (s + ( s << 3 ) ) + ( s << 8 ); // s * 265
  286. s = s ^ ( s >> 14 );
  287. s = ( s + ( s << 2 ) ) + ( s << 4 ); // s * 21
  288. s = s ^ ( s >> 28 );
  289. s = s + ( s << 31 );
  290. return (unsigned int)s;
  291. }
  292. // Based on the widely-used FNV-1A string hash with a final
  293. // mixing step to improve dispersion for very small and very
  294. // large hash table sizes.
  295. inline unsigned int StringHashFunctor::operator()( const char* s ) const
  296. {
  297. uint32 h = 2166136261u;
  298. for ( ; *s; ++s )
  299. {
  300. uint32 c = (unsigned char) *s;
  301. h = (h ^ c) * 16777619;
  302. }
  303. return (h ^ (h << 17)) + (h >> 21);
  304. }
  305. // Equivalent to StringHashFunctor on lower-case strings.
  306. inline unsigned int CaselessStringHashFunctor::operator()( const char* s ) const
  307. {
  308. uint32 h = 2166136261u;
  309. for ( ; *s; ++s )
  310. {
  311. uint32 c = (unsigned char) *s;
  312. // Brutally fast branchless ASCII tolower():
  313. // if ((c >= 'A') && (c <= 'Z')) c += ('a' - 'A');
  314. c += (((('A'-1) - c) & (c - ('Z'+1))) >> 26) & 32;
  315. h = (h ^ c) * 16777619;
  316. }
  317. return (h ^ (h << 17)) + (h >> 21);
  318. }
  319. #endif // UTLCOMMON_H