diff --git a/BAN/include/BAN/HashMap.h b/BAN/include/BAN/HashMap.h index ef2489db..45457962 100644 --- a/BAN/include/BAN/HashMap.h +++ b/BAN/include/BAN/HashMap.h @@ -1,49 +1,128 @@ #pragma once -#include -#include -#include +#include namespace BAN { - template> + template + class HashMapIterator + { + public: + HashMapIterator() = default; + + Entry& operator*() + { + return m_iterator.operator*(); + } + const Entry& operator*() const + { + return m_iterator.operator*(); + } + + Entry* operator->() + { + return m_iterator.operator->(); + } + const Entry* operator->() const + { + return m_iterator.operator->(); + } + + HashMapIterator& operator++() + { + ++m_iterator; + return *this; + } + HashMapIterator operator++(int) + { + auto temp = *this; + ++(*this); + return temp; + } + + bool operator==(HashMapIterator other) const + { + return m_iterator == other.m_iterator; + } + bool operator!=(HashMapIterator other) const + { + return m_iterator != other.m_iterator; + } + + private: + explicit HashMapIterator(HashSetIt it) + : m_iterator(it) + { } + + private: + HashSetIt m_iterator; + friend HashMap; + }; + + template, typename COMP = BAN::equal> class HashMap { public: struct Entry { - template - Entry(const Key& key, Args&&... args) requires is_constructible_v - : key(key) - , value(forward(args)...) - {} - - template - Entry(Key&& key, Args&&... args) requires is_constructible_v - : key(BAN::move(key)) - , value(forward(args)...) - {} - Key key; T value; }; + struct EntryHash + { + constexpr bool operator()(const Key& a) + { + return HASH()(a); + } + constexpr bool operator()(const Entry& a) + { + return HASH()(a.key); + } + }; + + struct EntryComp + { + constexpr bool operator()(const Entry& a, const Key& b) + { + return COMP()(a.key, b); + } + constexpr bool operator()(const Entry& a, const Entry& b) + { + return COMP()(a.key, b.key); + } + }; + public: - using size_type = size_t; - using key_type = Key; - using value_type = T; - using iterator = IteratorDouble; - using const_iterator = ConstIteratorDouble; + using size_type = size_t; + using key_type = Key; + using value_type = T; + using iterator = HashMapIterator::iterator, HashMap, Entry>; + using const_iterator = HashMapIterator::const_iterator, HashMap, const Entry>; public: HashMap() = default; - HashMap(const HashMap&); - HashMap(HashMap&&); - ~HashMap(); + ~HashMap() { clear(); } - HashMap& operator=(const HashMap&); - HashMap& operator=(HashMap&&); + HashMap(const HashMap& other) { *this = other; } + HashMap& operator=(const HashMap& other) + { + m_hash_set = other.m_hash_set; + return *this; + } + + HashMap(HashMap&& other) { *this = BAN::move(other); } + HashMap& operator=(HashMap&& other) + { + m_hash_set = BAN::move(other.m_hash_set); + return *this; + } + + iterator begin() { return iterator(m_hash_set.begin()); } + iterator end() { return iterator(m_hash_set.end()); } + const_iterator begin() const { return const_iterator(m_hash_set.begin()); } + const_iterator end() const { return const_iterator(m_hash_set.end()); } ErrorOr insert(const Key& key, const T& value) { return emplace(key, value); } ErrorOr insert(const Key& key, T&& value) { return emplace(key, move(value)); } @@ -57,263 +136,96 @@ namespace BAN template ErrorOr emplace(const Key& key, Args&&... args) requires is_constructible_v - { return emplace(Key(key), forward(args)...); } + { return emplace(Key(key), BAN::forward(args)...); } template - ErrorOr emplace(Key&&, Args&&...) requires is_constructible_v; + ErrorOr emplace(Key&& key, Args&&... args) requires is_constructible_v + { + ASSERT(!contains(key)); + auto it = TRY(m_hash_set.insert(Entry { BAN::move(key), T(BAN::forward(args)...) })); + return iterator(it); + } template ErrorOr emplace_or_assign(const Key& key, Args&&... args) requires is_constructible_v - { return emplace_or_assign(Key(key), forward(args)...); } + { return emplace_or_assign(Key(key), BAN::forward(args)...); } template - ErrorOr emplace_or_assign(Key&&, Args&&...) requires is_constructible_v; + ErrorOr emplace_or_assign(Key&& key, Args&&... args) requires is_constructible_v + { + if (auto it = m_hash_set.find(key); it != m_hash_set.end()) + { + it->value = T(BAN::forward(args)...); + return iterator(it); + } - iterator begin() { return iterator(m_buckets.end(), m_buckets.begin()); } - iterator end() { return iterator(m_buckets.end(), m_buckets.end()); } - const_iterator begin() const { return const_iterator(m_buckets.end(), m_buckets.begin()); } - const_iterator end() const { return const_iterator(m_buckets.end(), m_buckets.end()); } + auto it = TRY(m_hash_set.insert(Entry { BAN::move(key), T(BAN::forward(args)...) })); + return iterator(it); + } - ErrorOr reserve(size_type); + void remove(const Key& key) + { + if (auto it = find(key); it != end()) + remove(it); + } - void remove(const Key&); - void remove(iterator it); - void clear(); + iterator remove(iterator it) + { + return iterator(m_hash_set.remove(it.m_iterator)); + } - T& operator[](const Key&); - const T& operator[](const Key&) const; + template requires requires(const Key& a, const U& b) { COMP()(a, b); HASH()(b); } + iterator find(const U& key) + { + return iterator(m_hash_set.find(key)); + } - iterator find(const Key& key); - const_iterator find(const Key& key) const; - bool contains(const Key&) const; + template requires requires(const Key& a, const U& b) { COMP()(a, b); HASH()(b); } + const_iterator find(const U& key) const + { + return const_iterator(m_hash_set.find(key)); + } - bool empty() const; - size_type size() const; + void clear() + { + m_hash_set.clear(); + } + + ErrorOr reserve(size_type size) + { + return m_hash_set.reserve(size); + } + + T& operator[](const Key& key) + { + return find(key)->value; + } + + const T& operator[](const Key& key) const + { + return find(key)->value; + } + + bool contains(const Key& key) const + { + return find(key) != end(); + } + + size_type capacity() const + { + return m_hash_set.capacity(); + } + + size_type size() const + { + return m_hash_set.size(); + } + + bool empty() const + { + return m_hash_set.empty(); + } private: - ErrorOr rebucket(size_type); - LinkedList& get_bucket(const Key&); - const LinkedList& get_bucket(const Key&) const; - Vector>::iterator get_bucket_iterator(const Key&); - Vector>::const_iterator get_bucket_iterator(const Key&) const; - - private: - Vector> m_buckets; - size_type m_size = 0; - - friend iterator; + HashSet m_hash_set; }; - template - HashMap::HashMap(const HashMap& other) - { - *this = other; - } - - template - HashMap::HashMap(HashMap&& other) - { - *this = move(other); - } - - template - HashMap::~HashMap() - { - clear(); - } - - template - HashMap& HashMap::operator=(const HashMap& other) - { - clear(); - m_buckets = other.m_buckets; - m_size = other.m_size; - return *this; - } - - template - HashMap& HashMap::operator=(HashMap&& other) - { - clear(); - m_buckets = move(other.m_buckets); - m_size = other.m_size; - other.m_size = 0; - return *this; - } - - template - template - ErrorOr::iterator> HashMap::emplace(Key&& key, Args&&... args) requires is_constructible_v - { - ASSERT(!contains(key)); - TRY(rebucket(m_size + 1)); - - auto bucket_it = get_bucket_iterator(key); - TRY(bucket_it->emplace_back(move(key), forward(args)...)); - m_size++; - - return iterator(m_buckets.end(), bucket_it, prev(bucket_it->end(), 1)); - } - - template - template - ErrorOr::iterator> HashMap::emplace_or_assign(Key&& key, Args&&... args) requires is_constructible_v - { - if (empty()) - return emplace(move(key), forward(args)...); - - auto bucket_it = get_bucket_iterator(key); - for (auto entry_it = bucket_it->begin(); entry_it != bucket_it->end(); entry_it++) - { - if (entry_it->key != key) - continue; - entry_it->value = T(forward(args)...); - return iterator(m_buckets.end(), bucket_it, entry_it); - } - - return emplace(move(key), forward(args)...); - } - - template - ErrorOr HashMap::reserve(size_type size) - { - TRY(rebucket(size)); - return {}; - } - - template - void HashMap::remove(const Key& key) - { - auto it = find(key); - if (it != end()) - remove(it); - } - - template - void HashMap::remove(iterator it) - { - it.outer_current()->remove(it.inner_current()); - m_size--; - } - - template - void HashMap::clear() - { - m_buckets.clear(); - m_size = 0; - } - - template - T& HashMap::operator[](const Key& key) - { - ASSERT(!empty()); - auto& bucket = get_bucket(key); - for (Entry& entry : bucket) - if (entry.key == key) - return entry.value; - ASSERT_NOT_REACHED(); - } - - template - const T& HashMap::operator[](const Key& key) const - { - ASSERT(!empty()); - const auto& bucket = get_bucket(key); - for (const Entry& entry : bucket) - if (entry.key == key) - return entry.value; - ASSERT_NOT_REACHED(); - } - - template - typename HashMap::iterator HashMap::find(const Key& key) - { - if (empty()) - return end(); - auto bucket_it = get_bucket_iterator(key); - for (auto it = bucket_it->begin(); it != bucket_it->end(); it++) - if (it->key == key) - return iterator(m_buckets.end(), bucket_it, it); - return end(); - } - - template - typename HashMap::const_iterator HashMap::find(const Key& key) const - { - if (empty()) - return end(); - auto bucket_it = get_bucket_iterator(key); - for (auto it = bucket_it->begin(); it != bucket_it->end(); it++) - if (it->key == key) - return const_iterator(m_buckets.end(), bucket_it, it); - return end(); - } - - template - bool HashMap::contains(const Key& key) const - { - return find(key) != end(); - } - - template - bool HashMap::empty() const - { - return m_size == 0; - } - - template - typename HashMap::size_type HashMap::size() const - { - return m_size; - } - - template - ErrorOr HashMap::rebucket(size_type bucket_count) - { - if (m_buckets.size() >= bucket_count) - return {}; - - size_type new_bucket_count = BAN::Math::max(bucket_count, m_buckets.size() * 2); - Vector> new_buckets; - TRY(new_buckets.resize(new_bucket_count)); - - for (auto& bucket : m_buckets) - { - for (auto it = bucket.begin(); it != bucket.end();) - { - size_type new_bucket_index = HASH()(it->key) % new_buckets.size(); - it = bucket.move_element_to_other_linked_list(new_buckets[new_bucket_index], new_buckets[new_bucket_index].end(), it); - } - } - - m_buckets = move(new_buckets); - return {}; - } - - template - LinkedList::Entry>& HashMap::get_bucket(const Key& key) - { - return *get_bucket_iterator(key); - } - - template - const LinkedList::Entry>& HashMap::get_bucket(const Key& key) const - { - return *get_bucket_iterator(key); - } - - template - Vector::Entry>>::iterator HashMap::get_bucket_iterator(const Key& key) - { - ASSERT(!m_buckets.empty()); - auto index = HASH()(key) % m_buckets.size(); - return next(m_buckets.begin(), index); - } - - template - Vector::Entry>>::const_iterator HashMap::get_bucket_iterator(const Key& key) const - { - ASSERT(!m_buckets.empty()); - auto index = HASH()(key) % m_buckets.size(); - return next(m_buckets.begin(), index); - } - } diff --git a/userspace/libraries/LibInput/KeyboardLayout.cpp b/userspace/libraries/LibInput/KeyboardLayout.cpp index c3fa618e..55c3143a 100644 --- a/userspace/libraries/LibInput/KeyboardLayout.cpp +++ b/userspace/libraries/LibInput/KeyboardLayout.cpp @@ -19,20 +19,14 @@ namespace LibInput { - struct StringViewLower + struct StringViewLowerComp { - BAN::StringView value; - - StringViewLower(BAN::StringView sv) - : value(sv) - { } - - bool operator==(const StringViewLower& other) const + constexpr bool operator()(const BAN::StringView& a, const BAN::StringView& b) const { - if (value.size() != other.value.size()) + if (a.size() != b.size()) return false; - for (size_t i = 0; i < value.size(); i++) - if (tolower(value[i]) != tolower(other.value[i])) + for (size_t i = 0; i < a.size(); i++) + if (tolower(a[i]) != tolower(b[i])) return false; return true; } @@ -40,16 +34,16 @@ namespace LibInput struct StringViewLowerHash { - BAN::hash_t operator()(const StringViewLower& value) const + BAN::hash_t operator()(const BAN::StringView& str) const { constexpr BAN::hash_t FNV_offset_basis = 0x811c9dc5; constexpr BAN::hash_t FNV_prime = 0x01000193; BAN::hash_t hash = FNV_offset_basis; - for (size_t i = 0; i < value.value.size(); i++) + for (size_t i = 0; i < str.size(); i++) { hash *= FNV_prime; - hash ^= (uint8_t)tolower(value.value[i]); + hash ^= (uint8_t)tolower(str[i]); } return hash; @@ -113,7 +107,7 @@ namespace LibInput return keycode; } - static BAN::HashMap s_name_to_key; + static BAN::HashMap s_name_to_key; static BAN::ErrorOr initialize_name_to_key(); static BAN::Optional parse_key(BAN::StringView name) diff --git a/userspace/programs/resolver/main.cpp b/userspace/programs/resolver/main.cpp index 51ed2f12..53d1a5ce 100644 --- a/userspace/programs/resolver/main.cpp +++ b/userspace/programs/resolver/main.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include