From dcb4d1823fdf3cc2f7c9ce17fa216fe93fe2bfe3 Mon Sep 17 00:00:00 2001 From: "Justin C. Miller" Date: Tue, 15 Sep 2020 00:21:28 -0700 Subject: [PATCH] [kutil] Update map iteration Add an iterator type to kutil::map, and allow for each loops. Also unify the compare() signature expected by sorting containers, and fixes to adding and sorting in kutil::vector. --- src/kernel/frame_allocator.cpp | 6 +-- src/kernel/frame_allocator.h | 2 +- .../kutil/include/kutil/linked_list.h | 2 +- src/libraries/kutil/include/kutil/map.h | 27 +++++++++++++ src/libraries/kutil/include/kutil/vector.h | 38 +++++++++++++------ src/tests/container_helpers.h | 4 +- 6 files changed, 61 insertions(+), 18 deletions(-) diff --git a/src/kernel/frame_allocator.cpp b/src/kernel/frame_allocator.cpp index 0a91ec0..5751370 100644 --- a/src/kernel/frame_allocator.cpp +++ b/src/kernel/frame_allocator.cpp @@ -8,11 +8,11 @@ using memory::page_offset; using frame_block_node = kutil::list_node; int -frame_block::compare(const frame_block *rhs) const +frame_block::compare(const frame_block &rhs) const { - if (address < rhs->address) + if (address < rhs.address) return -1; - else if (address > rhs->address) + else if (address > rhs.address) return 1; return 0; } diff --git a/src/kernel/frame_allocator.h b/src/kernel/frame_allocator.h index ada2c5f..613fb68 100644 --- a/src/kernel/frame_allocator.h +++ b/src/kernel/frame_allocator.h @@ -46,6 +46,6 @@ struct frame_block /// Compare two blocks by address. /// \arg rhs The right-hand comparator /// \returns <0 if this is sorts earlier, >0 if this sorts later, 0 for equal - int compare(const frame_block *rhs) const; + int compare(const frame_block &rhs) const; }; diff --git a/src/libraries/kutil/include/kutil/linked_list.h b/src/libraries/kutil/include/kutil/linked_list.h index a7b94b0..b18cec2 100644 --- a/src/libraries/kutil/include/kutil/linked_list.h +++ b/src/libraries/kutil/include/kutil/linked_list.h @@ -321,7 +321,7 @@ public: if (!item) return; item_type *cur = m_head; - while (cur && item->compare(cur) > 0) + while (cur && item->compare(*cur) > 0) cur = cur->m_next; insert_before(cur, item); diff --git a/src/libraries/kutil/include/kutil/map.h b/src/libraries/kutil/include/kutil/map.h index 138b0c8..c67da49 100644 --- a/src/libraries/kutil/include/kutil/map.h +++ b/src/libraries/kutil/include/kutil/map.h @@ -70,6 +70,21 @@ public: static constexpr size_t min_capacity = 8; static constexpr size_t max_load = 90; + class iterator + { + public: + iterator(node *n) : m_node(n) {} + inline node & operator*() { return *m_node; } + inline node * operator->() { return m_node; } + inline const node & operator*() const { return *m_node; } + inline iterator & operator++() { incr(); return *this; } + inline iterator operator++(int) { node *old = m_node; incr(); return iterator(old); } + inline bool operator!=(const iterator &o) { return m_node != o.m_node; } + private: + void incr() { do { m_node++; } while ( m_node && m_node->hash() == 0 ); } + node *m_node; + }; + /// Default constructor. Creates an empty map with the given capacity. base_map(size_t capacity = 0) : m_count(0), @@ -86,6 +101,18 @@ public: kfree(m_nodes); } + iterator begin() { + return iterator(m_nodes); + } + + const iterator begin() const { + return iterator(m_nodes); + } + + const iterator end() const { + return iterator(m_nodes + m_capacity); + } + void insert(K k, V v) { if (++m_count > threshold()) grow(); insert_node(hash(k), std::move(k), std::move(v)); diff --git a/src/libraries/kutil/include/kutil/vector.h b/src/libraries/kutil/include/kutil/vector.h index e34297f..0ce5450 100644 --- a/src/libraries/kutil/include/kutil/vector.h +++ b/src/libraries/kutil/include/kutil/vector.h @@ -125,19 +125,21 @@ public: } /// Insert an item into the list in a sorted position. Depends on T - /// having a method `int compare(const T *other)`. - void sorted_insert(const T& item) + /// having a method `int compare(const T &other)`. + /// \returns index of the new item + size_t sorted_insert(const T& item) { size_t start = 0; size_t end = m_size; while (end > start) { size_t m = start + (end - start) / 2; - int c = item.compare(&m_elements[m]); + int c = item.compare(m_elements[m]); if (c < 0) end = m; else start = m + 1; } insert(start, item); + return start; } /// Remove an item from the end of the array. @@ -156,16 +158,30 @@ public: remove_at(0); } - /// Remove the item at the given index from the array, not - /// order-preserving. - void remove_at(size_t i) + /// Remove an item from the array. + void remove(const T &item) { - if (i >= count()) return; + kassert(m_size, "Called remove() on an empty array"); + for (size_t i = 0; i < m_size; ++i) { + if (m_elements[i] == item) { + remove_at(i); + break; + } + } + } - m_elements[i].~T(); - for (; i < m_size - 1; ++i) - m_elements[i] = m_elements[i+1]; - m_size -= 1; + /// Remove n items starting at the given index from the array, + /// order-preserving. + void remove_at(size_t i, size_t n = 1) + { + for (size_t j = i; j < i + n; ++j) { + if (j >= m_size) return; + m_elements[j].~T(); + } + + for (; i < m_size - n; ++i) + m_elements[i] = m_elements[i+n]; + m_size -= n; } /// Remove the first occurance of an item from the array, not diff --git a/src/tests/container_helpers.h b/src/tests/container_helpers.h index cee6d35..335dd9e 100644 --- a/src/tests/container_helpers.h +++ b/src/tests/container_helpers.h @@ -6,8 +6,8 @@ struct unsortableT { struct sortableT { int value; - int compare(const sortableT *other) const { - return value - other->value; + int compare(const sortableT &other) const { + return value - other.value; } };