diff --git a/AK/AKString.h b/AK/AKString.h index f99e954b40..bec22ec886 100755 --- a/AK/AKString.h +++ b/AK/AKString.h @@ -219,6 +219,12 @@ struct Traits : public GenericTraits { static void dump(const String& s) { kprintf("%s", s.characters()); } }; +struct CaseInsensitiveStringTraits : public AK::Traits { + 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; diff --git a/AK/HashMap.h b/AK/HashMap.h index 208bc18c49..554309fcfb 100644 --- a/AK/HashMap.h +++ b/AK/HashMap.h @@ -7,7 +7,7 @@ namespace AK { -template +template> class HashMap { private: struct Entry { @@ -16,12 +16,12 @@ private: }; struct EntryTraits { - static unsigned hash(const Entry& entry) { return Traits::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::dump(entry.key); + KeyTraits::dump(entry.key); kprintf(" value="); Traits::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::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::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); } diff --git a/AK/Tests/TestHashMap.cpp b/AK/Tests/TestHashMap.cpp index 0820cd9c42..55455b1d16 100644 --- a/AK/Tests/TestHashMap.cpp +++ b/AK/Tests/TestHashMap.cpp @@ -32,5 +32,14 @@ int main() EXPECT(number_to_string.find(3) == number_to_string.end()); EXPECT_EQ(loop_counter, 3); + + { + HashMap 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; } diff --git a/AK/Tests/TestString.cpp b/AK/Tests/TestString.cpp old mode 100755 new mode 100644