str_stl.h 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. #pragma once
  2. #include <util/memory/alloc.h>
  3. #include <util/digest/numeric.h>
  4. #include <util/generic/string.h>
  5. #include <util/generic/string_hash.h>
  6. #include <util/generic/strbuf.h>
  7. #include <util/generic/typetraits.h>
  8. #include <functional>
  9. #include <typeindex>
  10. #include <utility>
  11. namespace std {
  12. template <>
  13. struct less<const char*> {
  14. bool operator()(const char* x, const char* y) const {
  15. return strcmp(x, y) < 0;
  16. }
  17. };
  18. template <>
  19. struct equal_to<const char*> {
  20. bool operator()(const char* x, const char* y) const {
  21. return strcmp(x, y) == 0;
  22. }
  23. bool operator()(const char* x, const TStringBuf y) const {
  24. return strlen(x) == y.size() && memcmp(x, y.data(), y.size()) == 0;
  25. }
  26. using is_transparent = void;
  27. };
  28. }
  29. namespace NHashPrivate {
  30. template <class T, bool needNumericHashing>
  31. struct THashHelper {
  32. inline size_t operator()(const T& t) const noexcept {
  33. return (size_t)t; // If you have a compilation error here, look at explanation below:
  34. // Probably error is caused by undefined template specialization of THash<T>
  35. // You can find examples of specialization in this file
  36. }
  37. };
  38. template <class T>
  39. struct THashHelper<T, true> {
  40. inline size_t operator()(const T& t) const noexcept {
  41. return NumericHash(t);
  42. }
  43. };
  44. template <typename C>
  45. struct TStringHash {
  46. using is_transparent = void;
  47. inline size_t operator()(const TBasicStringBuf<C> s) const noexcept {
  48. return NHashPrivate::ComputeStringHash(s.data(), s.size());
  49. }
  50. };
  51. }
  52. template <class T>
  53. struct hash: public NHashPrivate::THashHelper<T, std::is_scalar<T>::value && !std::is_integral<T>::value> {
  54. };
  55. template <typename T>
  56. struct hash<const T*> {
  57. inline size_t operator()(const T* t) const noexcept {
  58. return NumericHash(t);
  59. }
  60. };
  61. template <class T>
  62. struct hash<T*>: public ::hash<const T*> {
  63. };
  64. template <>
  65. struct hash<const char*>: ::NHashPrivate::TStringHash<char> {
  66. };
  67. template <size_t n>
  68. struct hash<char[n]>: ::NHashPrivate::TStringHash<char> {
  69. };
  70. template <>
  71. struct THash<TStringBuf>: ::NHashPrivate::TStringHash<char> {
  72. };
  73. template <>
  74. struct THash<std::string_view>: ::NHashPrivate::TStringHash<char> {
  75. };
  76. template <>
  77. struct hash<TString>: ::NHashPrivate::TStringHash<char> {
  78. };
  79. template <>
  80. struct hash<TUtf16String>: ::NHashPrivate::TStringHash<wchar16> {
  81. };
  82. template <>
  83. struct THash<TWtringBuf>: ::NHashPrivate::TStringHash<wchar16> {
  84. };
  85. template <>
  86. struct hash<TUtf32String>: ::NHashPrivate::TStringHash<wchar32> {
  87. };
  88. template <>
  89. struct THash<TUtf32StringBuf>: ::NHashPrivate::TStringHash<wchar32> {
  90. };
  91. template <class C, class T, class A>
  92. struct hash<std::basic_string<C, T, A>>: ::NHashPrivate::TStringHash<C> {
  93. };
  94. template <>
  95. struct THash<std::type_index> {
  96. inline size_t operator()(const std::type_index& index) const {
  97. return index.hash_code();
  98. }
  99. };
  100. namespace NHashPrivate {
  101. template <typename T>
  102. Y_FORCE_INLINE static size_t HashObject(const T& val) {
  103. return THash<T>()(val);
  104. }
  105. template <size_t I, bool IsLastElement, typename... TArgs>
  106. struct TupleHashHelper {
  107. Y_FORCE_INLINE static size_t Hash(const std::tuple<TArgs...>& tuple) {
  108. return CombineHashes(HashObject(std::get<I>(tuple)),
  109. TupleHashHelper<I + 1, I + 2 >= sizeof...(TArgs), TArgs...>::Hash(tuple));
  110. }
  111. };
  112. template <size_t I, typename... TArgs>
  113. struct TupleHashHelper<I, true, TArgs...> {
  114. Y_FORCE_INLINE static size_t Hash(const std::tuple<TArgs...>& tuple) {
  115. return HashObject(std::get<I>(tuple));
  116. }
  117. };
  118. }
  119. template <typename... TArgs>
  120. struct THash<std::tuple<TArgs...>> {
  121. size_t operator()(const std::tuple<TArgs...>& tuple) const {
  122. return NHashPrivate::TupleHashHelper<0, 1 >= sizeof...(TArgs), TArgs...>::Hash(tuple);
  123. }
  124. };
  125. template <class T>
  126. struct THash: public ::hash<T> {
  127. };
  128. namespace NHashPrivate {
  129. template <class TFirst, class TSecond, bool IsEmpty = std::is_empty<THash<TFirst>>::value&& std::is_empty<THash<TSecond>>::value>
  130. struct TPairHash {
  131. private:
  132. THash<TFirst> FirstHash;
  133. THash<TSecond> SecondHash;
  134. public:
  135. template <class T>
  136. inline size_t operator()(const T& pair) const {
  137. return CombineHashes(FirstHash(pair.first), SecondHash(pair.second));
  138. }
  139. };
  140. /**
  141. * Specialization for the case where both hash functors are empty. Basically the
  142. * only one we care about. We don't introduce additional specializations for
  143. * cases where only one of the functors is empty as the code bloat is just not worth it.
  144. */
  145. template <class TFirst, class TSecond>
  146. struct TPairHash<TFirst, TSecond, true> {
  147. template <class T>
  148. inline size_t operator()(const T& pair) const {
  149. // maps have TFirst = const TFoo, which would make for an undefined specialization
  150. using TFirstClean = std::remove_cv_t<TFirst>;
  151. using TSecondClean = std::remove_cv_t<TSecond>;
  152. return CombineHashes(THash<TFirstClean>()(pair.first), THash<TSecondClean>()(pair.second));
  153. }
  154. };
  155. }
  156. template <class TFirst, class TSecond>
  157. struct hash<std::pair<TFirst, TSecond>>: public NHashPrivate::TPairHash<TFirst, TSecond> {
  158. };
  159. template <class T>
  160. struct TEqualTo: public std::equal_to<T> {
  161. };
  162. template <>
  163. struct TEqualTo<TString>: public TEqualTo<TStringBuf> {
  164. using is_transparent = void;
  165. };
  166. template <>
  167. struct TEqualTo<TUtf16String>: public TEqualTo<TWtringBuf> {
  168. using is_transparent = void;
  169. };
  170. template <>
  171. struct TEqualTo<TUtf32String>: public TEqualTo<TUtf32StringBuf> {
  172. using is_transparent = void;
  173. };
  174. template <class TFirst, class TSecond>
  175. struct TEqualTo<std::pair<TFirst, TSecond>> {
  176. template <class TOther>
  177. inline bool operator()(const std::pair<TFirst, TSecond>& a, const TOther& b) const {
  178. return TEqualTo<TFirst>()(a.first, b.first) && TEqualTo<TSecond>()(a.second, b.second);
  179. }
  180. using is_transparent = void;
  181. };
  182. template <class T>
  183. struct TCIEqualTo {
  184. };
  185. template <>
  186. struct TCIEqualTo<const char*> {
  187. inline bool operator()(const char* a, const char* b) const {
  188. return stricmp(a, b) == 0;
  189. }
  190. };
  191. template <>
  192. struct TCIEqualTo<TStringBuf> {
  193. inline bool operator()(const TStringBuf a, const TStringBuf b) const {
  194. return a.size() == b.size() && strnicmp(a.data(), b.data(), a.size()) == 0;
  195. }
  196. };
  197. template <>
  198. struct TCIEqualTo<TString> {
  199. inline bool operator()(const TString& a, const TString& b) const {
  200. return a.size() == b.size() && strnicmp(a.data(), b.data(), a.size()) == 0;
  201. }
  202. };
  203. template <class T>
  204. struct TLess: public std::less<T> {
  205. };
  206. template <>
  207. struct TLess<TString>: public TLess<TStringBuf> {
  208. using is_transparent = void;
  209. };
  210. template <>
  211. struct TLess<TUtf16String>: public TLess<TWtringBuf> {
  212. using is_transparent = void;
  213. };
  214. template <>
  215. struct TLess<TUtf32String>: public TLess<TUtf32StringBuf> {
  216. using is_transparent = void;
  217. };
  218. template <class T>
  219. struct TGreater: public std::greater<T> {
  220. };
  221. template <>
  222. struct TGreater<TString>: public TGreater<TStringBuf> {
  223. using is_transparent = void;
  224. };
  225. template <>
  226. struct TGreater<TUtf16String>: public TGreater<TWtringBuf> {
  227. using is_transparent = void;
  228. };
  229. template <>
  230. struct TGreater<TUtf32String>: public TGreater<TUtf32StringBuf> {
  231. using is_transparent = void;
  232. };