[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.
This commit is contained in:
2020-09-15 00:21:28 -07:00
parent e8564c755b
commit dcb4d1823f
6 changed files with 61 additions and 18 deletions

View File

@@ -8,11 +8,11 @@ using memory::page_offset;
using frame_block_node = kutil::list_node<frame_block>; using frame_block_node = kutil::list_node<frame_block>;
int 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; return -1;
else if (address > rhs->address) else if (address > rhs.address)
return 1; return 1;
return 0; return 0;
} }

View File

@@ -46,6 +46,6 @@ struct frame_block
/// Compare two blocks by address. /// Compare two blocks by address.
/// \arg rhs The right-hand comparator /// \arg rhs The right-hand comparator
/// \returns <0 if this is sorts earlier, >0 if this sorts later, 0 for equal /// \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;
}; };

View File

@@ -321,7 +321,7 @@ public:
if (!item) return; if (!item) return;
item_type *cur = m_head; item_type *cur = m_head;
while (cur && item->compare(cur) > 0) while (cur && item->compare(*cur) > 0)
cur = cur->m_next; cur = cur->m_next;
insert_before(cur, item); insert_before(cur, item);

View File

@@ -70,6 +70,21 @@ public:
static constexpr size_t min_capacity = 8; static constexpr size_t min_capacity = 8;
static constexpr size_t max_load = 90; 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. /// Default constructor. Creates an empty map with the given capacity.
base_map(size_t capacity = 0) : base_map(size_t capacity = 0) :
m_count(0), m_count(0),
@@ -86,6 +101,18 @@ public:
kfree(m_nodes); 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) { void insert(K k, V v) {
if (++m_count > threshold()) grow(); if (++m_count > threshold()) grow();
insert_node(hash(k), std::move(k), std::move(v)); insert_node(hash(k), std::move(k), std::move(v));

View File

@@ -125,19 +125,21 @@ public:
} }
/// Insert an item into the list in a sorted position. Depends on T /// Insert an item into the list in a sorted position. Depends on T
/// having a method `int compare(const T *other)`. /// having a method `int compare(const T &other)`.
void sorted_insert(const T& item) /// \returns index of the new item
size_t sorted_insert(const T& item)
{ {
size_t start = 0; size_t start = 0;
size_t end = m_size; size_t end = m_size;
while (end > start) { while (end > start) {
size_t m = start + (end - start) / 2; 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; if (c < 0) end = m;
else start = m + 1; else start = m + 1;
} }
insert(start, item); insert(start, item);
return start;
} }
/// Remove an item from the end of the array. /// Remove an item from the end of the array.
@@ -156,16 +158,30 @@ public:
remove_at(0); remove_at(0);
} }
/// Remove the item at the given index from the array, not /// Remove an item from the array.
/// order-preserving. void remove(const T &item)
void remove_at(size_t i)
{ {
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(); /// Remove n items starting at the given index from the array,
for (; i < m_size - 1; ++i) /// order-preserving.
m_elements[i] = m_elements[i+1]; void remove_at(size_t i, size_t n = 1)
m_size -= 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 /// Remove the first occurance of an item from the array, not

View File

@@ -6,8 +6,8 @@ struct unsortableT {
struct sortableT { struct sortableT {
int value; int value;
int compare(const sortableT *other) const { int compare(const sortableT &other) const {
return value - other->value; return value - other.value;
} }
}; };