AK: Support case-insensitive HashMap<String, T>.
We achieve this by allowing you to specify custom traits for the key type. For convenience, we also provide a CaseInsensitiveStringTraits for String.
This commit is contained in:
parent
b425de18cc
commit
d9d13f2445
Notes:
sideshowbarker
2024-07-19 13:18:29 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/d9d13f2445e
4 changed files with 22 additions and 6 deletions
|
@ -219,6 +219,12 @@ struct Traits<String> : public GenericTraits<String> {
|
|||
static void dump(const String& s) { kprintf("%s", s.characters()); }
|
||||
};
|
||||
|
||||
struct CaseInsensitiveStringTraits : public AK::Traits<String> {
|
||||
static unsigned hash(const String& s) { return s.impl() ? s.to_lowercase().impl()->hash() : 0; }
|
||||
static bool equals(const String& a, const String& b) { return a.to_lowercase() == b.to_lowercase(); }
|
||||
|
||||
};
|
||||
|
||||
inline bool operator<(const char* characters, const String& string)
|
||||
{
|
||||
if (!characters)
|
||||
|
@ -254,3 +260,4 @@ inline bool operator<=(const char* characters, const String& string)
|
|||
}
|
||||
|
||||
using AK::String;
|
||||
using AK::CaseInsensitiveStringTraits;
|
||||
|
|
12
AK/HashMap.h
12
AK/HashMap.h
|
@ -7,7 +7,7 @@
|
|||
|
||||
namespace AK {
|
||||
|
||||
template<typename K, typename V>
|
||||
template<typename K, typename V, typename KeyTraits = Traits<K>>
|
||||
class HashMap {
|
||||
private:
|
||||
struct Entry {
|
||||
|
@ -16,12 +16,12 @@ private:
|
|||
};
|
||||
|
||||
struct EntryTraits {
|
||||
static unsigned hash(const Entry& entry) { return Traits<K>::hash(entry.key); }
|
||||
static bool equals(const Entry& a, const Entry& b) { return a.key == b.key; }
|
||||
static unsigned hash(const Entry& entry) { return KeyTraits::hash(entry.key); }
|
||||
static bool equals(const Entry& a, const Entry& b) { return KeyTraits::equals(a.key, b.key); }
|
||||
static void dump(const Entry& entry)
|
||||
{
|
||||
kprintf("key=");
|
||||
Traits<K>::dump(entry.key);
|
||||
KeyTraits::dump(entry.key);
|
||||
kprintf(" value=");
|
||||
Traits<V>::dump(entry.value);
|
||||
}
|
||||
|
@ -51,11 +51,11 @@ public:
|
|||
|
||||
IteratorType begin() { return m_table.begin(); }
|
||||
IteratorType end() { return m_table.end(); }
|
||||
IteratorType find(const K& key) { return m_table.find(Traits<K>::hash(key), [&](auto& entry) { return key == entry.key; }); }
|
||||
IteratorType find(const K& key) { return m_table.find(KeyTraits::hash(key), [&](auto& entry) { return KeyTraits::equals(key, entry.key); }); }
|
||||
|
||||
ConstIteratorType begin() const { return m_table.begin(); }
|
||||
ConstIteratorType end() const { return m_table.end(); }
|
||||
ConstIteratorType find(const K& key) const { return m_table.find(Traits<K>::hash(key), [&](auto& entry) { return key == entry.key; }); }
|
||||
ConstIteratorType find(const K& key) const { return m_table.find(KeyTraits::hash(key), [&](auto& entry) { return KeyTraits::equals(key, entry.key); }); }
|
||||
|
||||
void ensure_capacity(int capacity) { m_table.ensure_capacity(capacity); }
|
||||
|
||||
|
|
|
@ -32,5 +32,14 @@ int main()
|
|||
EXPECT(number_to_string.find(3) == number_to_string.end());
|
||||
|
||||
EXPECT_EQ(loop_counter, 3);
|
||||
|
||||
{
|
||||
HashMap<String, int, CaseInsensitiveStringTraits> casemap;
|
||||
EXPECT_EQ(String("nickserv").to_lowercase(), String("NickServ").to_lowercase());
|
||||
casemap.set("nickserv", 3);
|
||||
casemap.set("NickServ", 3);
|
||||
EXPECT_EQ(casemap.size(), 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
0
AK/Tests/TestString.cpp
Executable file → Normal file
0
AK/Tests/TestString.cpp
Executable file → Normal file
Loading…
Add table
Reference in a new issue