123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 |
- #pragma once
- #include <util/memory/alloc.h>
- #include <util/digest/numeric.h>
- #include <util/generic/string.h>
- #include <util/generic/string_hash.h>
- #include <util/generic/strbuf.h>
- #include <util/generic/typetraits.h>
- #include <functional>
- #include <typeindex>
- #include <utility>
- #ifndef NO_CUSTOM_CHAR_PTR_STD_COMPARATOR
- namespace std {
- template <>
- struct less<const char*> {
- bool operator()(const char* x, const char* y) const {
- return strcmp(x, y) < 0;
- }
- };
- template <>
- struct equal_to<const char*> {
- bool operator()(const char* x, const char* y) const {
- return strcmp(x, y) == 0;
- }
- bool operator()(const char* x, const TStringBuf y) const {
- return strlen(x) == y.size() && memcmp(x, y.data(), y.size()) == 0;
- }
- using is_transparent = void;
- };
- }
- #endif
- namespace NHashPrivate {
- template <class T, bool needNumericHashing>
- struct THashHelper {
- using is_default_implementation = std::true_type;
- inline size_t operator()(const T& t) const noexcept {
- return (size_t)t; // If you have a compilation error here, look at explanation below:
- // Probably error is caused by undefined template specialization of THash<T>
- // You can find examples of specialization in this file
- }
- };
- template <class T>
- struct THashHelper<T, true> {
- inline size_t operator()(const T& t) const noexcept {
- return NumericHash(t);
- }
- };
- template <typename C>
- struct TStringHash {
- using is_transparent = void;
- inline size_t operator()(const TBasicStringBuf<C> s) const noexcept {
- return NHashPrivate::ComputeStringHash(s.data(), s.size());
- }
- };
- }
- template <class T>
- struct hash: public NHashPrivate::THashHelper<T, std::is_scalar<T>::value && !std::is_integral<T>::value> {
- };
- template <typename T>
- struct hash<const T*> {
- inline size_t operator()(const T* t) const noexcept {
- return NumericHash(t);
- }
- };
- template <class T>
- struct hash<T*>: public ::hash<const T*> {
- };
- template <>
- struct hash<const char*>: ::NHashPrivate::TStringHash<char> {
- };
- template <size_t n>
- struct hash<char[n]>: ::NHashPrivate::TStringHash<char> {
- };
- template <>
- struct THash<TStringBuf>: ::NHashPrivate::TStringHash<char> {
- };
- template <>
- struct THash<std::string_view>: ::NHashPrivate::TStringHash<char> {
- };
- template <>
- struct hash<TString>: ::NHashPrivate::TStringHash<char> {
- };
- template <>
- struct hash<TUtf16String>: ::NHashPrivate::TStringHash<wchar16> {
- };
- template <>
- struct THash<TWtringBuf>: ::NHashPrivate::TStringHash<wchar16> {
- };
- template <>
- struct hash<TUtf32String>: ::NHashPrivate::TStringHash<wchar32> {
- };
- template <>
- struct THash<TUtf32StringBuf>: ::NHashPrivate::TStringHash<wchar32> {
- };
- template <class C, class T, class A>
- struct hash<std::basic_string<C, T, A>>: ::NHashPrivate::TStringHash<C> {
- };
- template <>
- struct THash<std::type_index> {
- inline size_t operator()(const std::type_index& index) const {
- return index.hash_code();
- }
- };
- namespace NHashPrivate {
- template <typename T>
- Y_FORCE_INLINE static size_t HashObject(const T& val) {
- return THash<T>()(val);
- }
- template <size_t I, bool IsLastElement, typename... TArgs>
- struct TupleHashHelper {
- Y_FORCE_INLINE static size_t Hash(const std::tuple<TArgs...>& tuple) {
- return CombineHashes(HashObject(std::get<I>(tuple)),
- TupleHashHelper<I + 1, I + 2 >= sizeof...(TArgs), TArgs...>::Hash(tuple));
- }
- };
- template <size_t I, typename... TArgs>
- struct TupleHashHelper<I, true, TArgs...> {
- Y_FORCE_INLINE static size_t Hash(const std::tuple<TArgs...>& tuple) {
- return HashObject(std::get<I>(tuple));
- }
- };
- }
- template <typename... TArgs>
- struct THash<std::tuple<TArgs...>> {
- size_t operator()(const std::tuple<TArgs...>& tuple) const {
- return NHashPrivate::TupleHashHelper<0, 1 >= sizeof...(TArgs), TArgs...>::Hash(tuple);
- }
- };
- template <class T>
- struct THash: public ::hash<T> {
- };
- namespace NHashPrivate {
- template <class TFirst, class TSecond, bool IsEmpty = std::is_empty<THash<TFirst>>::value&& std::is_empty<THash<TSecond>>::value>
- struct TPairHash {
- private:
- THash<TFirst> FirstHash;
- THash<TSecond> SecondHash;
- public:
- template <class T>
- inline size_t operator()(const T& pair) const {
- return CombineHashes(FirstHash(pair.first), SecondHash(pair.second));
- }
- };
- /**
- * Specialization for the case where both hash functors are empty. Basically the
- * only one we care about. We don't introduce additional specializations for
- * cases where only one of the functors is empty as the code bloat is just not worth it.
- */
- template <class TFirst, class TSecond>
- struct TPairHash<TFirst, TSecond, true> {
- template <class T>
- inline size_t operator()(const T& pair) const {
- // maps have TFirst = const TFoo, which would make for an undefined specialization
- using TFirstClean = std::remove_cv_t<TFirst>;
- using TSecondClean = std::remove_cv_t<TSecond>;
- return CombineHashes(THash<TFirstClean>()(pair.first), THash<TSecondClean>()(pair.second));
- }
- };
- }
- template <class TFirst, class TSecond>
- struct hash<std::pair<TFirst, TSecond>>: public NHashPrivate::TPairHash<TFirst, TSecond> {
- };
- template <class T>
- struct TEqualTo: public std::equal_to<T> {
- };
- template <>
- struct TEqualTo<TString>: public TEqualTo<TStringBuf> {
- using is_transparent = void;
- };
- template <>
- struct TEqualTo<TUtf16String>: public TEqualTo<TWtringBuf> {
- using is_transparent = void;
- };
- template <>
- struct TEqualTo<TUtf32String>: public TEqualTo<TUtf32StringBuf> {
- using is_transparent = void;
- };
- template <class TFirst, class TSecond>
- struct TEqualTo<std::pair<TFirst, TSecond>> {
- template <class TOther>
- inline bool operator()(const std::pair<TFirst, TSecond>& a, const TOther& b) const {
- return TEqualTo<TFirst>()(a.first, b.first) && TEqualTo<TSecond>()(a.second, b.second);
- }
- using is_transparent = void;
- };
- template <class T>
- struct TCIEqualTo {
- };
- template <>
- struct TCIEqualTo<const char*> {
- inline bool operator()(const char* a, const char* b) const {
- return stricmp(a, b) == 0;
- }
- };
- template <>
- struct TCIEqualTo<TStringBuf> {
- inline bool operator()(const TStringBuf a, const TStringBuf b) const {
- return a.size() == b.size() && strnicmp(a.data(), b.data(), a.size()) == 0;
- }
- };
- template <>
- struct TCIEqualTo<TString> {
- inline bool operator()(const TString& a, const TString& b) const {
- return a.size() == b.size() && strnicmp(a.data(), b.data(), a.size()) == 0;
- }
- };
- template <class T>
- struct TLess: public std::less<T> {
- };
- template <>
- struct TLess<TString>: public TLess<TStringBuf> {
- using is_transparent = void;
- };
- template <>
- struct TLess<TUtf16String>: public TLess<TWtringBuf> {
- using is_transparent = void;
- };
- template <>
- struct TLess<TUtf32String>: public TLess<TUtf32StringBuf> {
- using is_transparent = void;
- };
- template <class T>
- struct TGreater: public std::greater<T> {
- };
- template <>
- struct TGreater<TString>: public TGreater<TStringBuf> {
- using is_transparent = void;
- };
- template <>
- struct TGreater<TUtf16String>: public TGreater<TWtringBuf> {
- using is_transparent = void;
- };
- template <>
- struct TGreater<TUtf32String>: public TGreater<TUtf32StringBuf> {
- using is_transparent = void;
- };
|