libluna: Implement hash table iteration
All checks were successful
Build and test / build (push) Successful in 1m47s

This commit is contained in:
apio 2024-07-02 20:51:28 +02:00
parent 903dcfa52c
commit 7345a952ca
Signed by: apio
GPG Key ID: B8A7D06E42258954
3 changed files with 104 additions and 0 deletions

View File

@ -154,6 +154,16 @@ template <typename K, typename V> struct HashMap
m_table.clear(); m_table.clear();
} }
const HashTable<HashPair<K, V>>::HashTableIterator begin()
{
return m_table.begin();
}
const HashTable<HashPair<K, V>>::HashTableIterator end()
{
return m_table.end();
}
private: private:
HashTable<HashPair<K, V>> m_table; HashTable<HashPair<K, V>> m_table;
}; };

View File

@ -12,6 +12,8 @@
#include <luna/Heap.h> #include <luna/Heap.h>
#include <luna/Option.h> #include <luna/Option.h>
template <typename K, typename V> class HashMap;
/** /**
* @brief A table of values with best-case constant time lookup. * @brief A table of values with best-case constant time lookup.
* *
@ -181,6 +183,77 @@ template <typename T> class HashTable
clear(); clear();
} }
struct HashTableIterator
{
private:
HashTableIterator(usize index, HashTable<T>& table) : m_table(table)
{
if (index != -1)
{
m_index = index;
return;
}
for (usize i = 0; i < m_table.m_capacity; i++)
{
auto& opt = m_table.m_buckets[i];
if (opt.has_value())
{
m_index = i;
return;
}
}
m_index = m_table.m_capacity;
}
mutable usize m_index;
HashTable<T>& m_table;
public:
T& operator*()
{
return *m_table.m_buckets[m_index].value_ptr();
}
const T& operator*() const
{
return *m_table.m_buckets[m_index].value_ptr();
}
void operator++() const
{
for (usize i = m_index + 1; i < m_table.m_capacity; i++)
{
auto& opt = m_table.m_buckets[i];
if (opt.has_value())
{
m_index = i;
return;
}
}
m_index = m_table.m_capacity;
}
bool operator!=(HashTableIterator& other) const
{
return m_index != other.m_index || &m_table != &other.m_table;
}
friend class HashTable<T>;
};
const HashTableIterator begin()
{
return { (usize)-1, *this };
}
const HashTableIterator end()
{
return { m_capacity, *this };
}
private: private:
bool should_grow() bool should_grow()
{ {
@ -223,4 +296,6 @@ template <typename T> class HashTable
usize m_size { 0 }; usize m_size { 0 };
// FIXME: Randomize this to protect against hash table attacks. // FIXME: Randomize this to protect against hash table attacks.
u64 m_salt { 0 }; u64 m_salt { 0 };
friend class HashTableIterator;
}; };

View File

@ -80,6 +80,24 @@ TestResult test_hash_map_set_and_get()
test_success; test_success;
} }
TestResult test_hash_table_iteration()
{
HashTable<int> table;
validate(TRY(table.try_set(1)));
validate(TRY(table.try_set(2)));
validate(TRY(table.try_set(3)));
validate(TRY(table.try_set(4)));
int sum = 0;
for (const int& value : table) { sum += value; }
validate(sum == 10);
test_success;
}
Result<void> test_main() Result<void> test_main()
{ {
test_prelude; test_prelude;
@ -89,6 +107,7 @@ Result<void> test_main()
run_test(test_hash_table_remove); run_test(test_hash_table_remove);
run_test(test_hash_table_duplicates); run_test(test_hash_table_duplicates);
run_test(test_hash_map_set_and_get); run_test(test_hash_map_set_and_get);
run_test(test_hash_table_iteration);
return {}; return {};
} }