From da9c03ffb56112d9bbf93210b0b2fdf326bd48b2 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Fri, 7 Sep 2018 10:40:04 +0100 Subject: [PATCH] Implement std::hash support for evmc_bytes32 Uses FNV1a hash with 64-bit result. --- include/evmc/helpers.hpp | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/include/evmc/helpers.hpp b/include/evmc/helpers.hpp index b35a080..5f173c3 100644 --- a/include/evmc/helpers.hpp +++ b/include/evmc/helpers.hpp @@ -16,6 +16,7 @@ #include #include +#include /// The comparator for std::map. bool operator<(const evmc_address& a, const evmc_address& b) @@ -41,4 +42,39 @@ bool operator==(const evmc_bytes32& a, const evmc_bytes32& b) return std::memcmp(a.bytes, b.bytes, sizeof(a)) == 0; } +/// FNV1a hash function with 64-bit result. +static inline uint64_t fnv1a_64(const uint8_t* ptr, size_t len) +{ + constexpr uint64_t prime = 1099511628211ULL; + constexpr uint64_t offset_basis = 14695981039346656037ULL; + + uint64_t ret = offset_basis; + for (size_t i = 0; i < len; i++) + { + ret ^= ptr[i]; + ret *= prime; + } + return ret; +} + +static_assert(sizeof(size_t) == sizeof(uint64_t), "size_t is not 64-bit wide"); + +namespace std +{ +/// Hash operator template needed for std::ordered_set and others using hashes. +template <> +struct hash +{ + /// The argument type. + typedef evmc_bytes32 argument_type; + /// The result type. + typedef std::size_t result_type; + /// Hash operator using FNV1a. + result_type operator()(argument_type const& s) const noexcept + { + return fnv1a_64(s.bytes, sizeof(s.bytes)); + } +}; +} // namespace std + /** @} */