const uint32_t FNV_32_HASH_START = 2166136261UL;
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) {
// forcing signed char, since other platforms can use unsigned
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
*/
EXPECT_EQ(h2(a3), h2(a3.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}));