mirror of https://github.com/status-im/evmc.git
helpers: Extend fnv1a implementation to support 32-bit architectures
This commit is contained in:
parent
a6a98d19b1
commit
52689e049e
|
@ -53,17 +53,43 @@ inline bool is_zero(const evmc_bytes32& x) noexcept
|
||||||
return x == evmc_bytes32{};
|
return x == evmc_bytes32{};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// FNV1a hash function with 64-bit result.
|
/// Parameters for the fnv1a hash function, specialized by the hash result size (size_t).
|
||||||
inline uint64_t fnv1a_64(const uint8_t* ptr, size_t len)
|
///
|
||||||
|
/// The values for the matching size are taken from
|
||||||
|
/// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV_hash_parameters.
|
||||||
|
///
|
||||||
|
/// @tparam size The size of the hash result (size_t).
|
||||||
|
template <size_t size>
|
||||||
|
struct fnv1_params
|
||||||
{
|
{
|
||||||
constexpr uint64_t prime = 1099511628211ULL;
|
};
|
||||||
constexpr uint64_t offset_basis = 14695981039346656037ULL;
|
|
||||||
|
|
||||||
uint64_t ret = offset_basis;
|
/// Parameters for the fnv1a hash function, specialized for the hash result of 4 bytes.
|
||||||
|
template <>
|
||||||
|
struct fnv1_params<4>
|
||||||
|
{
|
||||||
|
static constexpr auto prime = 0x1000193; ///< The FNV prime.
|
||||||
|
static constexpr auto offset_basis = 0x811c9dc5; ///< The FNV offset basis.
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Parameters for the fnv1a hash function, specialized for the hash result of 8 bytes.
|
||||||
|
template <>
|
||||||
|
struct fnv1_params<8>
|
||||||
|
{
|
||||||
|
static constexpr auto prime = 0x100000001b3; ///< The FNV prime.
|
||||||
|
static constexpr auto offset_basis = 0xcbf29ce484222325; ///< The FNV offset basis.
|
||||||
|
};
|
||||||
|
|
||||||
|
/// FNV1a hash function.
|
||||||
|
inline size_t fnv1a(const uint8_t* ptr, size_t len) noexcept
|
||||||
|
{
|
||||||
|
using params = fnv1_params<sizeof(size_t)>;
|
||||||
|
|
||||||
|
auto ret = size_t{params::offset_basis};
|
||||||
for (size_t i = 0; i < len; i++)
|
for (size_t i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
ret ^= ptr[i];
|
ret ^= ptr[i];
|
||||||
ret *= prime;
|
ret *= params::prime;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -75,10 +101,9 @@ template <>
|
||||||
struct hash<evmc_address>
|
struct hash<evmc_address>
|
||||||
{
|
{
|
||||||
/// Hash operator using FNV1a.
|
/// Hash operator using FNV1a.
|
||||||
std::enable_if<sizeof(size_t) == 8, std::size_t>::type operator()(const evmc_address& s) const
|
size_t operator()(const evmc_address& s) const noexcept
|
||||||
noexcept
|
|
||||||
{
|
{
|
||||||
return fnv1a_64(s.bytes, sizeof(s.bytes));
|
return fnv1a(s.bytes, sizeof(s.bytes));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -87,10 +112,9 @@ template <>
|
||||||
struct hash<evmc_bytes32>
|
struct hash<evmc_bytes32>
|
||||||
{
|
{
|
||||||
/// Hash operator using FNV1a.
|
/// Hash operator using FNV1a.
|
||||||
std::enable_if<sizeof(size_t) == 8, std::size_t>::type operator()(const evmc_bytes32& s) const
|
size_t operator()(const evmc_bytes32& s) const noexcept
|
||||||
noexcept
|
|
||||||
{
|
{
|
||||||
return fnv1a_64(s.bytes, sizeof(s.bytes));
|
return fnv1a(s.bytes, sizeof(s.bytes));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
|
@ -30,6 +30,13 @@ static constexpr size_t optionalDataSize =
|
||||||
static_assert(optionalDataSize == sizeof(evmc_result_optional_storage), "");
|
static_assert(optionalDataSize == sizeof(evmc_result_optional_storage), "");
|
||||||
|
|
||||||
|
|
||||||
|
TEST(helpers, fnv1a)
|
||||||
|
{
|
||||||
|
const uint8_t text[] = {'E', 'V', 'M', 'C'};
|
||||||
|
const auto h = fnv1a(text, sizeof(text));
|
||||||
|
EXPECT_EQ(h, sizeof(size_t) == 8 ? 0x15e05d6d22fed89a : 0xffaa6a9a);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(helpers, maps)
|
TEST(helpers, maps)
|
||||||
{
|
{
|
||||||
std::map<evmc_address, bool> addresses;
|
std::map<evmc_address, bool> addresses;
|
||||||
|
|
Loading…
Reference in New Issue