Commit b3698ed4 authored by Subodh Iyengar's avatar Subodh Iyengar Committed by Facebook Github Bot

Add fnv1-a hash to Hash

Summary:
Add fnv1-a 64 bit hash to Hash.h.
fnv1-a is supposed to be preferred over
fnv1.

Reviewed By: yfeldblum

Differential Revision: D5453401

fbshipit-source-id: c13f12ef11eb6745c95f3901b14ceafce90ea0ea
parent 5d8920df
...@@ -214,6 +214,7 @@ inline uint32_t jenkins_rev_unmix32(uint32_t key) { ...@@ -214,6 +214,7 @@ inline uint32_t jenkins_rev_unmix32(uint32_t key) {
const uint32_t FNV_32_HASH_START = 2166136261UL; const uint32_t FNV_32_HASH_START = 2166136261UL;
const uint64_t FNV_64_HASH_START = 14695981039346656037ULL; const uint64_t FNV_64_HASH_START = 14695981039346656037ULL;
const uint64_t FNVA_64_HASH_START = 14695981039346656037ULL;
inline uint32_t fnv32(const char* buf, uint32_t hash = FNV_32_HASH_START) { inline uint32_t fnv32(const char* buf, uint32_t hash = FNV_32_HASH_START) {
// forcing signed char, since other platforms can use unsigned // forcing signed char, since other platforms can use unsigned
...@@ -278,6 +279,24 @@ inline uint64_t fnv64(const std::string& str, ...@@ -278,6 +279,24 @@ inline uint64_t fnv64(const std::string& str,
return fnv64_buf(str.data(), str.size(), hash); return fnv64_buf(str.data(), str.size(), hash);
} }
inline uint64_t fnva64_buf(const void* buf,
size_t n,
uint64_t hash = FNVA_64_HASH_START) {
const uint8_t* char_buf = reinterpret_cast<const uint8_t*>(buf);
for (size_t i = 0; i < n; ++i) {
hash ^= char_buf[i];
hash += (hash << 1) + (hash << 4) + (hash << 5) + (hash << 7) +
(hash << 8) + (hash << 40);
}
return hash;
}
inline uint64_t fnva64(const std::string& str,
uint64_t hash = FNVA_64_HASH_START) {
return fnva64_buf(str.data(), str.size(), hash);
}
/* /*
* Paul Hsieh: http://www.azillionmonkeys.com/qed/hash.html * Paul Hsieh: http://www.azillionmonkeys.com/qed/hash.html
*/ */
......
...@@ -376,3 +376,45 @@ TEST(Hash, Strings) { ...@@ -376,3 +376,45 @@ TEST(Hash, Strings) {
EXPECT_EQ(h2(a3), h2(a3.str())); EXPECT_EQ(h2(a3), h2(a3.str()));
EXPECT_EQ(h2(a4), h2(a4.str())); EXPECT_EQ(h2(a4), h2(a4.str()));
} }
struct FNVTestParam {
std::string in;
uint64_t out;
};
class FNVTest : public ::testing::TestWithParam<FNVTestParam> {};
TEST_P(FNVTest, Fnva64Buf) {
EXPECT_EQ(GetParam().out,
fnva64_buf(GetParam().in.data(), GetParam().in.size()));
}
TEST_P(FNVTest, Fnva64) {
EXPECT_EQ(GetParam().out, fnva64(GetParam().in));
}
TEST_P(FNVTest, Fnva64Partial) {
size_t partialLen = GetParam().in.size() / 2;
auto data = GetParam().in.data();
auto partial = fnva64_buf(data, partialLen);
EXPECT_EQ(GetParam().out,
fnva64_buf(
data + partialLen, GetParam().in.size() - partialLen, partial));
}
// Taken from http://www.isthe.com/chongo/src/fnv/test_fnv.c
INSTANTIATE_TEST_CASE_P(
FNVTesting,
FNVTest,
::testing::Values(
(FNVTestParam){"foobar", // 11
0x85944171f73967e8},
(FNVTestParam){"chongo was here!\n", // 39
0x46810940eff5f915},
(FNVTestParam){"127.0.0.3", // 106,
0xaabafc7104d91158},
(FNVTestParam){
"http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash", // 126
0xd9b957fb7fe794c5},
(FNVTestParam){"http://norvig.com/21-days.html", // 136
0x07aaa640476e0b9a}));
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment