str_stl.h 7.6 KB

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