mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 08:17:45 +00:00
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
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()); }
|
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)
|
inline bool operator<(const char* characters, const String& string)
|
||||||
{
|
{
|
||||||
if (!characters)
|
if (!characters)
|
||||||
|
@ -254,3 +260,4 @@ inline bool operator<=(const char* characters, const String& string)
|
||||||
}
|
}
|
||||||
|
|
||||||
using AK::String;
|
using AK::String;
|
||||||
|
using AK::CaseInsensitiveStringTraits;
|
||||||
|
|
12
AK/HashMap.h
12
AK/HashMap.h
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
namespace AK {
|
namespace AK {
|
||||||
|
|
||||||
template<typename K, typename V>
|
template<typename K, typename V, typename KeyTraits = Traits<K>>
|
||||||
class HashMap {
|
class HashMap {
|
||||||
private:
|
private:
|
||||||
struct Entry {
|
struct Entry {
|
||||||
|
@ -16,12 +16,12 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EntryTraits {
|
struct EntryTraits {
|
||||||
static unsigned hash(const Entry& entry) { return Traits<K>::hash(entry.key); }
|
static unsigned hash(const Entry& entry) { return KeyTraits::hash(entry.key); }
|
||||||
static bool equals(const Entry& a, const Entry& b) { return a.key == b.key; }
|
static bool equals(const Entry& a, const Entry& b) { return KeyTraits::equals(a.key, b.key); }
|
||||||
static void dump(const Entry& entry)
|
static void dump(const Entry& entry)
|
||||||
{
|
{
|
||||||
kprintf("key=");
|
kprintf("key=");
|
||||||
Traits<K>::dump(entry.key);
|
KeyTraits::dump(entry.key);
|
||||||
kprintf(" value=");
|
kprintf(" value=");
|
||||||
Traits<V>::dump(entry.value);
|
Traits<V>::dump(entry.value);
|
||||||
}
|
}
|
||||||
|
@ -51,11 +51,11 @@ public:
|
||||||
|
|
||||||
IteratorType begin() { return m_table.begin(); }
|
IteratorType begin() { return m_table.begin(); }
|
||||||
IteratorType end() { return m_table.end(); }
|
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 begin() const { return m_table.begin(); }
|
||||||
ConstIteratorType end() const { return m_table.end(); }
|
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); }
|
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(number_to_string.find(3) == number_to_string.end());
|
||||||
|
|
||||||
EXPECT_EQ(loop_counter, 3);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
0
AK/Tests/TestString.cpp
Executable file → Normal file
0
AK/Tests/TestString.cpp
Executable file → Normal file
Loading…
Add table
Add a link
Reference in a new issue