str_stl.h 7.4 KB

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