diff --git a/lib/glacier/CMakeLists.txt b/lib/glacier/CMakeLists.txt index 259b811..22bc6ac 100644 --- a/lib/glacier/CMakeLists.txt +++ b/lib/glacier/CMakeLists.txt @@ -4,6 +4,7 @@ set(glacier_files string/string_view.cpp string/str_format.cpp string/str_split.cpp + util/hash.cpp ) add_library(glacier STATIC diff --git a/lib/glacier/container/hash_map.h b/lib/glacier/container/hash_map.h index 81c5c31..65506b8 100644 --- a/lib/glacier/container/hash_map.h +++ b/lib/glacier/container/hash_map.h @@ -7,35 +7,11 @@ #include "glacier/container/pair.h" #include "glacier/status/error.h" #include "glacier/string/string.h" +#include "glacier/util/hash.h" namespace glcr { -template -struct HashFunc { - uint64_t operator()(const T&); -}; - -template <> -struct HashFunc { - uint64_t operator()(const uint64_t& value) { - // FIXME: Write a real hash function. - return 0xABBAABBAABBAABBA ^ value; - } -}; - -template <> -struct HashFunc { - uint64_t operator()(const String& value) { - // FIXME: Write a real hash function. - uint64_t acc = 0; - for (uint64_t i = 0; i < value.length(); i++) { - acc += value[i]; - } - return 0xABBAABBAABBAABBA ^ acc; - } -}; - -template > +template > class HashMap { public: HashMap() = default; diff --git a/lib/glacier/util/hash.cpp b/lib/glacier/util/hash.cpp new file mode 100644 index 0000000..214d8b9 --- /dev/null +++ b/lib/glacier/util/hash.cpp @@ -0,0 +1,30 @@ +#include "util/hash.h" + +#include "string/string.h" + +namespace glcr { +namespace { + +const uint64_t kFnvOffset = 0xcbf29ce484222325; +const uint64_t kFnvPrime = 0x100000001b3; + +} // namespace + +uint64_t Hash::operator()(const uint64_t& value) { + uint64_t hash = kFnvOffset; + for (uint8_t i = 0; i < 8; i++) { + hash *= kFnvPrime; + hash ^= (value >> (8 * i)) & 0xFF; + } + return hash; +} +uint64_t Hash::operator()(const String& value) { + uint64_t hash = kFnvOffset; + for (uint8_t i = 0; i < value.length(); i++) { + hash *= kFnvPrime; + hash ^= value[i]; + } + return hash; +} + +} // namespace glcr diff --git a/lib/glacier/util/hash.h b/lib/glacier/util/hash.h new file mode 100644 index 0000000..a92383c --- /dev/null +++ b/lib/glacier/util/hash.h @@ -0,0 +1,27 @@ +#pragma once + +#include + +namespace glcr { + +// General purpose templated hash function. +// Currently the template speciializations +// implement FNV hashing: +// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function +template +struct Hash { + uint64_t operator()(const T&); +}; + +template <> +struct Hash { + uint64_t operator()(const uint64_t&); +}; + +class String; +template <> +struct Hash { + uint64_t operator()(const String&); +}; + +} // namespace glcr