Skip to content

Commit

Permalink
hashlib: golf
Browse files Browse the repository at this point in the history
  • Loading branch information
widlarizer committed Sep 19, 2024
1 parent c3c3a7e commit fcbf0d3
Showing 1 changed file with 23 additions and 115 deletions.
138 changes: 23 additions & 115 deletions kernel/hashlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<typename T, typename Tag = general_tag>
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<typename T>
struct hash_ops_impl<T, integral_tag> {
// If this fails, adapt hash_ops<uint64_t>
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<typename T>
struct hash_ops_impl<T, enum_tag> {
using u_type = std::underlying_type_t<T>;
static inline Hasher hash_acc(T value, Hasher h) {
return hash_ops_impl<u_type, integral_tag>::hash_acc((u_type) value, h);
}
static inline bool cmp(T a, T b) {
return a == b;
}
};
// Hash pointers like pointer-sized ints
template<typename T>
struct hash_ops_impl<T, pointer_tag> {
static inline Hasher hash_acc(T value, Hasher h) {
return hash_ops_impl<uintptr_t, integral_tag>::hash_acc((uintptr_t) value, h);
}
static inline bool cmp(T a, T b) {
return a == b;
}
};

template<typename T>
struct hash_ops {
typedef hash_ops_impl<T, typename
std::conditional_t<
std::is_enum_v<T>,
enum_tag,

std::conditional_t<
std::is_pointer_v<T>,
pointer_tag,

std::conditional_t<
std::is_integral_v<T>,
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<typename T>
static inline bool cmp(T a, T b) {
return a == b;
}
};
template<> struct hash_ops<bool> : hash_int_ops
{
static inline Hasher hash_acc(bool a, Hasher h) {
return hash_ops_impl<bool, integral_tag>::hash_acc(a ? 1 : 0, h);
}
};

template<> struct hash_ops<uint32_t> : hash_int_ops
{
static inline Hasher hash_acc(uint32_t a, Hasher h) {
h.hash32(a);
return h;
}
};
template<> struct hash_ops<uint64_t> : 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<int32_t> : hash_ops<uint32_t> {};
template<> struct hash_ops<int64_t> : hash_ops<uint64_t> {};

template<> struct hash_ops<std::string> {
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<T, bool>) {
h.hash32(a ? 1 : 0);
return h;
} else if constexpr (std::is_integral_v<T>) {
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<T>) {
using u_type = std::underlying_type_t<T>;
return hash_ops<u_type>::hash_acc((u_type) a, h);
} else if constexpr (std::is_pointer_v<T>) {
return hash_ops<uintptr_t>::hash_acc((uintptr_t) a, h);
} else if constexpr (std::is_same_v<T, std::string>) {
for (auto c : a)
h.hash32(c);
return h;
} else {
return a.hash_acc(h);
}
}
};

Expand Down

0 comments on commit fcbf0d3

Please sign in to comment.