diff --git a/kernel/hashlib.h b/kernel/hashlib.h index ec95ef08c0c..ccbf771bd86 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -100,126 +100,34 @@ class Hasher { }; #endif - -// Tag structs -struct general_tag {}; -struct integral_tag : general_tag {}; -struct enum_tag : general_tag {}; -struct pointer_tag : general_tag {}; - -template -struct hash_ops_impl { - static inline bool cmp(const T &a, const T &b) { - return a == b; - } - static inline Hasher hash_acc(const T &a, Hasher h) { - return a.hash_acc(h); - } -}; -// Unless they're too big, -// hash integers as the size natural to the hasher. -template -struct hash_ops_impl { - // If this fails, adapt hash_ops - static_assert(sizeof(T) <= sizeof(uint64_t)); - static inline Hasher hash_acc(T value, Hasher h) { - if (sizeof(T) == sizeof(uint64_t)) - h.hash64(value); - else - h.hash32(value); - - return h; - } - static inline bool cmp(T a, T b) { - return a == b; - } -}; -// Hash enums like their underlying type -template -struct hash_ops_impl { - using u_type = std::underlying_type_t; - static inline Hasher hash_acc(T value, Hasher h) { - return hash_ops_impl::hash_acc((u_type) value, h); - } - static inline bool cmp(T a, T b) { - return a == b; - } -}; -// Hash pointers like pointer-sized ints -template -struct hash_ops_impl { - static inline Hasher hash_acc(T value, Hasher h) { - return hash_ops_impl::hash_acc((uintptr_t) value, h); - } - static inline bool cmp(T a, T b) { - return a == b; - } -}; - template struct hash_ops { - typedef hash_ops_impl, - enum_tag, - - std::conditional_t< - std::is_pointer_v, - pointer_tag, - - std::conditional_t< - std::is_integral_v, - integral_tag, - - general_tag>>>> impl; - static inline Hasher hash_acc(const T &a, Hasher h) { - return impl::hash_acc(a, h); - } static inline bool cmp(const T &a, const T &b) { - return impl::cmp(a, b); - } -}; - -struct hash_int_ops { - template - static inline bool cmp(T a, T b) { - return a == b; - } -}; -template<> struct hash_ops : hash_int_ops -{ - static inline Hasher hash_acc(bool a, Hasher h) { - return hash_ops_impl::hash_acc(a ? 1 : 0, h); - } -}; - -template<> struct hash_ops : hash_int_ops -{ - static inline Hasher hash_acc(uint32_t a, Hasher h) { - h.hash32(a); - return h; - } -}; -template<> struct hash_ops : hash_int_ops -{ - static inline Hasher hash_acc(uint64_t a, Hasher h) { - h.hash64(a); - return h; - } -}; - -// Explicit specializations to ensure the correct types are used -template<> struct hash_ops : hash_ops {}; -template<> struct hash_ops : hash_ops {}; - -template<> struct hash_ops { - static inline bool cmp(const std::string &a, const std::string &b) { return a == b; } - static inline Hasher hash_acc(const std::string &a, Hasher h) { - for (auto c : a) - h.hash32(c); - return h; + static inline Hasher hash_acc(const T &a, Hasher h) { + if constexpr (std::is_same_v) { + h.hash32(a ? 1 : 0); + return h; + } else if constexpr (std::is_integral_v) { + static_assert(sizeof(T) <= sizeof(uint64_t)); + if (sizeof(T) == sizeof(uint64_t)) + h.hash64(a); + else + h.hash32(a); + return h; + } else if constexpr (std::is_enum_v) { + using u_type = std::underlying_type_t; + return hash_ops::hash_acc((u_type) a, h); + } else if constexpr (std::is_pointer_v) { + return hash_ops::hash_acc((uintptr_t) a, h); + } else if constexpr (std::is_same_v) { + for (auto c : a) + h.hash32(c); + return h; + } else { + return a.hash_acc(h); + } } };