diff --git a/AK/AKString.h b/AK/AKString.h index 886819b85e2..a7de84b8564 100644 --- a/AK/AKString.h +++ b/AK/AKString.h @@ -203,7 +203,7 @@ inline bool StringView::operator==(const String& string) const } template<> -struct Traits { +struct Traits : public GenericTraits { static unsigned hash(const String& s) { return s.impl() ? s.impl()->hash() : 0; } static void dump(const String& s) { kprintf("%s", s.characters()); } }; diff --git a/AK/DoublyLinkedList.h b/AK/DoublyLinkedList.h index 1d30c8a1c7e..5fe83b309ed 100644 --- a/AK/DoublyLinkedList.h +++ b/AK/DoublyLinkedList.h @@ -1,7 +1,8 @@ #pragma once -#include "StdLibExtras.h" #include +#include +#include namespace AK { @@ -116,7 +117,7 @@ public: ConstIterator find(const T& value) const { for (auto* node = m_head; node; node = node->next) { - if (node->value == value) + if (Traits::equals(node->value, value)) return ConstIterator(node); } return end(); @@ -125,7 +126,7 @@ public: Iterator find(const T& value) { for (auto* node = m_head; node; node = node->next) { - if (node->value == value) + if (Traits::equals(node->value, value)) return Iterator(node); } return end(); diff --git a/AK/HashMap.h b/AK/HashMap.h index ea85b805a4b..d6fed82763b 100644 --- a/AK/HashMap.h +++ b/AK/HashMap.h @@ -13,15 +13,11 @@ private: struct Entry { K key; V value; - - bool operator==(const Entry& other) const - { - return key == other.key; - } }; 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 void dump(const Entry& entry) { kprintf("key="); diff --git a/AK/HashTable.h b/AK/HashTable.h index 346d65bfe02..0e10730e6ac 100644 --- a/AK/HashTable.h +++ b/AK/HashTable.h @@ -181,7 +181,7 @@ void HashTable::set(T&& value) rehash(1); auto& bucket = lookup(value); for (auto& e : bucket) { - if (e == value) { + if (TraitsForT::equals(e, value)) { e = move(value); return; } @@ -202,7 +202,7 @@ void HashTable::set(const T& value) rehash(1); auto& bucket = lookup(value); for (auto& e : bucket) { - if (e == value) { + if (TraitsForT::equals(e, value)) { e = value; return; } @@ -267,7 +267,7 @@ bool HashTable::contains(const T& value) const return false; auto& bucket = lookup(value); for (auto& e : bucket) { - if (e == value) + if (TraitsForT::equals(e, value)) return true; } return false; @@ -280,7 +280,7 @@ auto HashTable::find(const T& value) -> Iterator return end(); int bucket_index; auto& bucket = lookup(value, &bucket_index); - auto bucket_iterator = bucket.find(value); + auto bucket_iterator = bucket.template find(value); if (bucket_iterator != bucket.end()) return Iterator(*this, false, bucket_iterator, bucket_index); return end(); @@ -293,7 +293,7 @@ auto HashTable::find(const T& value) const -> ConstIterator return end(); int bucket_index; const auto& bucket = lookup(value, &bucket_index); - auto bucket_iterator = bucket.find(value); + auto bucket_iterator = bucket.template find(value); if (bucket_iterator != bucket.end()) return ConstIterator(*this, false, bucket_iterator, bucket_index); return end(); diff --git a/AK/IPv4Address.h b/AK/IPv4Address.h index 56dc3d57ce0..d3d1bf1dfa0 100644 --- a/AK/IPv4Address.h +++ b/AK/IPv4Address.h @@ -52,7 +52,7 @@ private: static_assert(sizeof(IPv4Address) == 4); template<> -struct Traits { +struct Traits : public GenericTraits { static unsigned hash(const IPv4Address& address) { return string_hash((const char*)&address, sizeof(address)); } static void dump(const IPv4Address& address) { kprintf("%s", address.to_string().characters()); } }; diff --git a/AK/OwnPtr.h b/AK/OwnPtr.h index 64168e85960..c301323553c 100644 --- a/AK/OwnPtr.h +++ b/AK/OwnPtr.h @@ -109,9 +109,10 @@ make(Args&&... args) } template -struct Traits> { +struct Traits> : public GenericTraits> { static unsigned hash(const OwnPtr& p) { return (unsigned)p.ptr(); } static void dump(const OwnPtr& p) { kprintf("%p", p.ptr()); } + static bool equals(const OwnPtr& a, const OwnPtr& b) { return a.ptr() == b.ptr(); } }; } diff --git a/AK/SinglyLinkedList.h b/AK/SinglyLinkedList.h index d6d55b5917e..59b2f1665a7 100644 --- a/AK/SinglyLinkedList.h +++ b/AK/SinglyLinkedList.h @@ -169,6 +169,30 @@ public: return end(); } + template + ConstIterator find(const T& value) const + { + Node* prev = nullptr; + for (auto* node = m_head; node; node = node->next) { + if (Traits::equals(node->value, value)) + return ConstIterator(node, prev); + prev = node; + } + return end(); + } + + template + Iterator find(const T& value) + { + Node* prev = nullptr; + for (auto* node = m_head; node; node = node->next) { + if (Traits::equals(node->value, value)) + return Iterator(node, prev); + prev = node; + } + return end(); + } + void remove(Iterator iterator) { ASSERT(!iterator.is_end()); diff --git a/AK/Traits.h b/AK/Traits.h index f0ecb9ae2df..63080b58838 100644 --- a/AK/Traits.h +++ b/AK/Traits.h @@ -6,25 +6,30 @@ namespace AK { template -struct Traits { +struct GenericTraits { + static bool equals(const T& a, const T& b) { return a == b; } +}; + +template +struct Traits : public GenericTraits { }; template<> -struct Traits { +struct Traits : public GenericTraits { static unsigned hash(int i) { return int_hash(i); } static void dump(int i) { kprintf("%d", i); } }; template<> -struct Traits { +struct Traits : public GenericTraits { static unsigned hash(unsigned u) { return int_hash(u); } static void dump(unsigned u) { kprintf("%u", u); } }; template<> -struct Traits { - static unsigned hash(unsigned u) { return int_hash(u); } - static void dump(unsigned u) { kprintf("%u", u); } +struct Traits : public GenericTraits { + static unsigned hash(word u) { return int_hash(u); } + static void dump(word u) { kprintf("%u", u); } }; template @@ -34,6 +39,7 @@ struct Traits { return int_hash((unsigned)(__PTRDIFF_TYPE__)p); } static void dump(const T* p) { kprintf("%p", p); } + static bool equals(const T* a, const T* b) { return a == b; } }; } diff --git a/AK/Vector.h b/AK/Vector.h index 1ae11d6cabc..176b05d9ff8 100644 --- a/AK/Vector.h +++ b/AK/Vector.h @@ -2,22 +2,24 @@ #include #include +#include #include // NOTE: We can't include during the toolchain bootstrap, // since it's part of libstdc++, and libstdc++ depends on LibC. // For this reason, we don't support Vector(initializer_list) in LibC. #ifndef SERENITY_LIBC_BUILD -#include +# include #endif #ifndef __serenity__ -#include +# include #endif namespace AK { -template class Vector; +template +class Vector; template class VectorIterator { @@ -148,7 +150,7 @@ public: bool contains_slow(const T& value) const { for (int i = 0; i < size(); ++i) { - if (at(i) == value) + if (Traits::equals(at(i), value)) return true; } return false; diff --git a/Applications/Taskbar/WindowIdentifier.h b/Applications/Taskbar/WindowIdentifier.h index f5fcd65bfc1..7d849d36ec1 100644 --- a/Applications/Taskbar/WindowIdentifier.h +++ b/Applications/Taskbar/WindowIdentifier.h @@ -26,7 +26,7 @@ private: namespace AK { template<> -struct Traits { +struct Traits : public GenericTraits { static unsigned hash(const WindowIdentifier& w) { return pair_int_hash(w.client_id(), w.window_id()); } static void dump(const WindowIdentifier& w) { kprintf("WindowIdentifier(%d, %d)", w.client_id(), w.window_id()); } }; diff --git a/Kernel/FileSystem/DiskBackedFileSystem.cpp b/Kernel/FileSystem/DiskBackedFileSystem.cpp index d8b66803a1d..6a3f8ddc908 100644 --- a/Kernel/FileSystem/DiskBackedFileSystem.cpp +++ b/Kernel/FileSystem/DiskBackedFileSystem.cpp @@ -15,7 +15,7 @@ struct BlockIdentifier { namespace AK { template<> -struct Traits { +struct Traits : public GenericTraits { static unsigned hash(const BlockIdentifier& block_id) { return pair_int_hash(block_id.fsid, block_id.index); } static void dump(const BlockIdentifier& block_id) { kprintf("[block %02u:%08u]", block_id.fsid, block_id.index); } }; diff --git a/Kernel/FileSystem/FileSystem.h b/Kernel/FileSystem/FileSystem.h index 58f839faef2..55d48a4ff8e 100644 --- a/Kernel/FileSystem/FileSystem.h +++ b/Kernel/FileSystem/FileSystem.h @@ -89,7 +89,7 @@ inline bool InodeIdentifier::is_root_inode() const namespace AK { template<> -struct Traits { +struct Traits : public GenericTraits { static unsigned hash(const InodeIdentifier& inode) { return pair_int_hash(inode.fsid(), inode.index()); } static void dump(const InodeIdentifier& inode) { kprintf("%02u:%08u", inode.fsid(), inode.index()); } }; diff --git a/Kernel/Net/MACAddress.h b/Kernel/Net/MACAddress.h index 3cf906decb6..72069bdaa5d 100644 --- a/Kernel/Net/MACAddress.h +++ b/Kernel/Net/MACAddress.h @@ -40,7 +40,7 @@ static_assert(sizeof(MACAddress) == 6); namespace AK { template<> -struct Traits { +struct Traits : public GenericTraits { static unsigned hash(const MACAddress& address) { return string_hash((const char*)&address, sizeof(address)); } static void dump(const MACAddress& address) { kprintf("%s", address.to_string().characters()); } }; diff --git a/LibGUI/GShortcut.h b/LibGUI/GShortcut.h index 20713eb0f50..808fca41368 100644 --- a/LibGUI/GShortcut.h +++ b/LibGUI/GShortcut.h @@ -32,7 +32,7 @@ private: namespace AK { template<> -struct Traits { +struct Traits : public GenericTraits { static unsigned hash(const GShortcut& shortcut) { return pair_int_hash(shortcut.modifiers(), shortcut.key());