mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-21 23:20:20 +00:00
AK: Define a traits helper for case-insensitive StringView hashing
Currently, we define a CaseInsensitiveStringTraits structure for String. Using this structure for StringView involves allocating a String from that view, and a second string to convert that intermediate string to lowercase. This defines CaseInsensitiveStringViewTraits (and the underlying helper case_insensitive_string_hash) to avoid allocations.
This commit is contained in:
parent
7d9b6b41c3
commit
3dccaa39d8
Notes:
sideshowbarker
2024-07-17 21:13:55 +09:00
Author: https://github.com/trflynn89 Commit: https://github.com/SerenityOS/serenity/commit/3dccaa39d8e Pull-request: https://github.com/SerenityOS/serenity/pull/11799 Reviewed-by: https://github.com/linusg ✅
3 changed files with 43 additions and 0 deletions
|
@ -24,6 +24,27 @@ constexpr u32 string_hash(char const* characters, size_t length, u32 seed = 0)
|
|||
return hash;
|
||||
}
|
||||
|
||||
constexpr u32 case_insensitive_string_hash(char const* characters, size_t length, u32 seed = 0)
|
||||
{
|
||||
// AK/CharacterTypes.h cannot be included from here.
|
||||
auto to_lowercase = [](char ch) -> u32 {
|
||||
if (ch >= 'A' && ch <= 'Z')
|
||||
return static_cast<u32>(ch) + 0x20;
|
||||
return static_cast<u32>(ch);
|
||||
};
|
||||
|
||||
u32 hash = seed;
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
hash += to_lowercase(characters[i]);
|
||||
hash += (hash << 10);
|
||||
hash ^= (hash >> 6);
|
||||
}
|
||||
hash += hash << 3;
|
||||
hash ^= hash >> 11;
|
||||
hash += hash << 15;
|
||||
return hash;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
using AK::string_hash;
|
||||
|
|
|
@ -221,6 +221,15 @@ struct Traits<StringView> : public GenericTraits<StringView> {
|
|||
static unsigned hash(StringView s) { return s.hash(); }
|
||||
};
|
||||
|
||||
struct CaseInsensitiveStringViewTraits : public Traits<StringView> {
|
||||
static unsigned hash(StringView s)
|
||||
{
|
||||
if (s.is_empty())
|
||||
return 0;
|
||||
return case_insensitive_string_hash(s.characters_without_null_termination(), s.length());
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
[[nodiscard]] ALWAYS_INLINE constexpr AK::StringView operator"" sv(const char* cstring, size_t length)
|
||||
|
@ -228,4 +237,5 @@ struct Traits<StringView> : public GenericTraits<StringView> {
|
|||
return AK::StringView(cstring, length);
|
||||
}
|
||||
|
||||
using AK::CaseInsensitiveStringViewTraits;
|
||||
using AK::StringView;
|
||||
|
|
|
@ -189,3 +189,15 @@ TEST_CASE(constexpr_stuff)
|
|||
}
|
||||
#undef do_test
|
||||
}
|
||||
|
||||
TEST_CASE(case_insensitive_hash)
|
||||
{
|
||||
auto string1 = "abcdef"sv;
|
||||
auto string2 = "ABCDEF"sv;
|
||||
auto string3 = "aBcDeF"sv;
|
||||
auto string4 = "foo"sv;
|
||||
|
||||
EXPECT_EQ(CaseInsensitiveStringViewTraits::hash(string1), CaseInsensitiveStringViewTraits::hash(string2));
|
||||
EXPECT_EQ(CaseInsensitiveStringViewTraits::hash(string1), CaseInsensitiveStringViewTraits::hash(string3));
|
||||
EXPECT_NE(CaseInsensitiveStringViewTraits::hash(string1), CaseInsensitiveStringViewTraits::hash(string4));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue