diff --git a/AK/DoublyLinkedList.h b/AK/DoublyLinkedList.h index 0ddf61dbe3..fe65bb6264 100644 --- a/AK/DoublyLinkedList.h +++ b/AK/DoublyLinkedList.h @@ -40,10 +40,12 @@ public: { auto* node = new Node(std::move(value)); if (!m_head) { + ASSERT(!m_tail); m_head = node; m_tail = node; return; } + ASSERT(m_tail); m_tail->next = node; node->prev = m_tail; m_tail = node; @@ -112,14 +114,20 @@ public: { ASSERT(it.m_node); auto* node = it.m_node; - if (node->prev) + if (node->prev) { + ASSERT(node != m_head); node->prev->next = node->next; - if (node->next) - node->next->prev = node->prev; - if (m_head == node) + } else { + ASSERT(node == m_head); m_head = node->next; - if (m_tail == node) + } + if (node->next) { + ASSERT(node != m_tail); + node->next->prev = node->prev; + } else { + ASSERT(node == m_tail); m_tail = node->prev; + } delete node; } diff --git a/AK/HashTable.h b/AK/HashTable.h index 4de631a582..e42c3c4dbe 100644 --- a/AK/HashTable.h +++ b/AK/HashTable.h @@ -104,8 +104,9 @@ public: } private: friend class HashTable; - explicit Iterator(HashTable& table, bool isEnd, typename DoublyLinkedList::Iterator bucketIterator = DoublyLinkedList::Iterator::universalEnd()) + explicit Iterator(HashTable& table, bool isEnd, typename DoublyLinkedList::Iterator bucketIterator = DoublyLinkedList::Iterator::universalEnd(), unsigned bucketIndex = 0) : m_table(table) + , m_bucketIndex(bucketIndex) , m_isEnd(isEnd) , m_bucketIterator(bucketIterator) { @@ -179,8 +180,9 @@ public: } private: friend class HashTable; - ConstIterator(const HashTable& table, bool isEnd, typename DoublyLinkedList::ConstIterator bucketIterator = DoublyLinkedList::ConstIterator::universalEnd()) + ConstIterator(const HashTable& table, bool isEnd, typename DoublyLinkedList::ConstIterator bucketIterator = DoublyLinkedList::ConstIterator::universalEnd(), unsigned bucketIndex = 0) : m_table(table) + , m_bucketIndex(bucketIndex) , m_isEnd(isEnd) , m_bucketIterator(bucketIterator) { @@ -217,8 +219,8 @@ public: void remove(Iterator&); private: - Bucket& lookup(const T&); - const Bucket& lookup(const T&) const; + Bucket& lookup(const T&, unsigned* bucketIndex = nullptr); + const Bucket& lookup(const T&, unsigned* bucketIndex = nullptr) const; void rehash(unsigned capacity); void insert(T&&); @@ -305,10 +307,11 @@ auto HashTable::find(const T& value) -> Iterator { if (isEmpty()) return end(); - auto& bucket = lookup(value); + unsigned bucketIndex; + auto& bucket = lookup(value, &bucketIndex); auto bucketIterator = bucket.chain.find(value); if (bucketIterator != bucket.chain.end()) - return Iterator(*this, false, bucketIterator); + return Iterator(*this, false, bucketIterator, bucketIndex); return end(); } @@ -317,10 +320,11 @@ auto HashTable::find(const T& value) const -> ConstIterator { if (isEmpty()) return end(); - auto& bucket = lookup(value); + unsigned bucketIndex; + auto& bucket = lookup(value, &bucketIndex); auto bucketIterator = bucket.chain.find(value); if (bucketIterator != bucket.chain.end()) - return ConstIterator(*this, false, bucketIterator); + return ConstIterator(*this, false, bucketIterator, bucketIndex); return end(); } @@ -333,7 +337,7 @@ void HashTable::remove(Iterator& it) } template -typename HashTable::Bucket& HashTable::lookup(const T& value) +typename HashTable::Bucket& HashTable::lookup(const T& value, unsigned* bucketIndex) { unsigned hash = TraitsForT::hash(value); #ifdef HASHTABLE_DEBUG @@ -341,11 +345,13 @@ typename HashTable::Bucket& HashTable::lookup(cons TraitsForT::dump(value); printf(" is %u\n", hash); #endif + if (bucketIndex) + *bucketIndex = hash % m_capacity; return m_buckets[hash % m_capacity]; } template -const typename HashTable::Bucket& HashTable::lookup(const T& value) const +const typename HashTable::Bucket& HashTable::lookup(const T& value, unsigned* bucketIndex) const { unsigned hash = TraitsForT::hash(value); #ifdef HASHTABLE_DEBUG @@ -353,6 +359,8 @@ const typename HashTable::Bucket& HashTable::looku TraitsForT::dump(value); printf(" is %u\n", hash); #endif + if (bucketIndex) + *bucketIndex = hash % m_capacity; return m_buckets[hash % m_capacity]; }