Skip to content

Commit d04dbbf

Browse files
committed
Add the first 31 bytes to the hash of long strings
1 parent 0b28a37 commit d04dbbf

File tree

2 files changed

+14
-13
lines changed

2 files changed

+14
-13
lines changed

src/core/json/include/sourcemeta/core/json_hash.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ template <typename T> struct PropertyHashJSON {
4949
-> hash_type {
5050
hash_type result;
5151
assert(!value.empty());
52-
assert(value.size() <= 31);
5352
// Copy starting a byte 2
5453
std::memcpy(reinterpret_cast<char *>(&result) + 1, value.data(), size);
5554
return result;
@@ -126,17 +125,19 @@ template <typename T> struct PropertyHashJSON {
126125
// This case is specifically designed to be constant with regards to
127126
// string length, and to exploit the fact that most JSON objects don't
128127
// have a lot of entries, so hash collision is not as common
129-
return {(size + static_cast<typename hash_type::type>(value.front()) +
130-
static_cast<typename hash_type::type>(value.back())) %
131-
// Make sure the property hash can never exceed 8 bits
132-
256};
128+
auto hash = this->perfect(value, 31);
129+
hash.a |= (size + static_cast<typename hash_type::type>(value.front()) +
130+
static_cast<typename hash_type::type>(value.back())) %
131+
// Make sure the property hash can never exceed 8 bits
132+
256;
133+
return hash;
133134
}
134135
}
135136

136137
inline auto is_perfect(const hash_type &hash) const noexcept -> bool {
137138
// If there is anything written past the first byte,
138139
// then it is a perfect hash
139-
return hash.a > 255;
140+
return (hash.a & 255) == 0;
140141
}
141142
};
142143

test/json/json_hash_test.cc

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ TEST(JSON_key_hash, hash_empty) {
77
hasher;
88
const sourcemeta::core::JSON::String value{""};
99
const auto hash{hasher(value)};
10-
EXPECT_FALSE(hasher.is_perfect(hash));
10+
EXPECT_TRUE(hasher.is_perfect(hash));
1111
#if defined(__SIZEOF_INT128__)
1212
EXPECT_EQ(hash.a,
1313
(__uint128_t{0x0000000000000000} << 64) | 0x0000000000000000);
@@ -619,14 +619,14 @@ TEST(JSON_key_hash, hash_fooooooooooooooooooooooooooooooo) {
619619
EXPECT_FALSE(hasher.is_perfect(hash));
620620
#if defined(__SIZEOF_INT128__)
621621
EXPECT_EQ(hash.a,
622-
(__uint128_t{0x0000000000000000} << 64) | 0x00000000000000f5);
622+
(__uint128_t{0x6f6f6f6f6f6f6f6f} << 64) | 0x6f6f6f6f6f6f66f5);
623623
EXPECT_EQ(hash.b,
624-
(__uint128_t{0x0000000000000000} << 64) | 0x0000000000000000);
624+
(__uint128_t{0x6f6f6f6f6f6f6f6f} << 64) | 0x6f6f6f6f6f6f6f6f);
625625
#else
626626
// 0x20 (length) + 0x66 (f) + 0x6f (o)
627-
EXPECT_EQ(hash.a, 0x00000000000000f5);
628-
EXPECT_EQ(hash.b, 0x0000000000000000);
629-
EXPECT_EQ(hash.c, 0x0000000000000000);
630-
EXPECT_EQ(hash.d, 0x0000000000000000);
627+
EXPECT_EQ(hash.a, 0x6f6f6f6f6f6f66f5);
628+
EXPECT_EQ(hash.b, 0x6f6f6f6f6f6f6f6f);
629+
EXPECT_EQ(hash.c, 0x6f6f6f6f6f6f6f6f);
630+
EXPECT_EQ(hash.d, 0x6f6f6f6f6f6f6f6f);
631631
#endif
632632
}

0 commit comments

Comments
 (0)