comparer.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. typedef uint hash_t;
  7. #define TAGHASH(hash) ((static_cast<hash_t>(hash) << 1) | 1)
  8. #define UNTAGHASH(hash) (static_cast<hash_t>(hash) >> 1)
  9. // This comparer can create good hash codes and comparisons for all value,
  10. // pointer and string types using template specialization.
  11. template <typename T>
  12. struct DefaultComparer
  13. {
  14. __inline static bool Equals(const T &x, const T &y)
  15. {
  16. return x == y;
  17. }
  18. __inline static hash_t GetHashCode(const T &i)
  19. {
  20. return (hash_t)i;
  21. }
  22. };
  23. template <>
  24. struct DefaultComparer<double>
  25. {
  26. __inline static bool Equals(double x, double y)
  27. {
  28. return x == y;
  29. }
  30. __inline static hash_t GetHashCode(double d)
  31. {
  32. __int64 i64 = *(__int64*)&d;
  33. return (uint)((i64>>32) ^ (uint)i64);
  34. }
  35. };
  36. template <typename T>
  37. struct DefaultComparer<T *>
  38. {
  39. __inline static bool Equals(T * x, T * y)
  40. {
  41. return x == y;
  42. }
  43. __inline static hash_t GetHashCode(T * i)
  44. {
  45. // Shifting helps us eliminate any sameness due to our alignment strategy.
  46. // TODO: This works for Arena memory only. Recycler memory is 16 byte aligned.
  47. // Find a good universal hash for pointers.
  48. uint hash = (uint)(((size_t)i) >> ArenaAllocator::ObjectAlignmentBitShift);
  49. return hash;
  50. }
  51. };
  52. template <>
  53. struct DefaultComparer<size_t>
  54. {
  55. __inline static bool Equals(size_t x, size_t y)
  56. {
  57. return x == y;
  58. }
  59. __inline static uint GetHashCode(size_t i)
  60. {
  61. #if _WIN64
  62. // For 64 bits we want all 64 bits of the pointer to be represented in the hash code.
  63. uint32 hi = ((UINT_PTR) i >> 32);
  64. uint32 lo = (uint32) (i & 0xFFFFFFFF);
  65. uint hash = hi ^ lo;
  66. #else
  67. uint hash = i;
  68. #endif
  69. return hash;
  70. }
  71. static int Compare(size_t i1, size_t i2)
  72. {
  73. if (i1 < i2)
  74. {
  75. return -1;
  76. }
  77. else if (i1 > i2)
  78. {
  79. return 1;
  80. }
  81. else
  82. {
  83. return 0;
  84. }
  85. }
  86. };
  87. // This specialization does a better job of creating hash codes
  88. // for recycler pointers.
  89. template <typename T>
  90. struct RecyclerPointerComparer
  91. {
  92. __inline static bool Equals(T x, T y)
  93. {
  94. return x == y;
  95. }
  96. __inline static hash_t GetHashCode(T i)
  97. {
  98. // Shifting helps us eliminate any sameness due to our alignment strategy.
  99. // TODO: This works for Recycler memory only. Arena memory is 8 byte aligned.
  100. // Find a good universal hash for pointers.
  101. uint hash = (uint)(((size_t)i) >> HeapConstants::ObjectAllocationShift);
  102. return hash;
  103. }
  104. };
  105. template <>
  106. struct DefaultComparer<GUID>
  107. {
  108. __inline static bool Equals(GUID const& x, GUID const& y)
  109. {
  110. return x == y;
  111. }
  112. __inline static hash_t GetHashCode(GUID const& guid)
  113. {
  114. char* p = (char*)&guid;
  115. int hash = 0;
  116. for (int i = 0; i < sizeof(GUID); i++)
  117. {
  118. hash = _rotl(hash, 7);
  119. hash ^= (uint32)(p[i]);
  120. }
  121. return hash;
  122. }
  123. };
  124. template<typename T>
  125. struct StringComparer
  126. {
  127. __inline static bool Equals(T str1, T str2)
  128. {
  129. return ::wcscmp(str1, str2) == 0;
  130. }
  131. __inline static hash_t GetHashCode(T str)
  132. {
  133. int hash = 0;
  134. while (*str)
  135. {
  136. hash = _rotl(hash, 7);
  137. hash ^= *str;
  138. str++;
  139. }
  140. return hash;
  141. }
  142. static int Compare(T str1, T str2)
  143. {
  144. return ::wcscmp(str1, str2);
  145. }
  146. };
  147. template<>
  148. struct DefaultComparer<WCHAR*> : public StringComparer<WCHAR*> {};
  149. template<>
  150. struct DefaultComparer<const WCHAR*> : public StringComparer<const WCHAR*> {};
  151. template <typename T, typename TComparer>
  152. struct SpecializedComparer
  153. {
  154. template <typename T> class TComparerType;
  155. template <> class TComparerType<T> : public TComparer {};
  156. };
  157. namespace regex
  158. {
  159. template <class T> struct Comparer
  160. {
  161. public:
  162. virtual bool Equals(T item1, T item2) = 0;
  163. virtual int GetHashCode(T item) = 0;
  164. virtual int Compare(T item1, T item2) = 0;
  165. };
  166. }