mirror of
https://github.com/zebrajr/ladybird.git
synced 2025-12-06 00:19:53 +01:00
AK: Add Vector::remove_all(container)/remove_all(it, end)
Instead of repeatedly removing elements off the vector, this allows for specifying all the removed indices at once, and does not perform any extra reallocations or unnecessary moves.
This commit is contained in:
parent
93d7efa4c3
commit
80e5356853
38
AK/Vector.h
38
AK/Vector.h
|
|
@ -503,6 +503,44 @@ public:
|
|||
update_metadata();
|
||||
}
|
||||
|
||||
/// The iterator pair identify a set of indices *in ascending order* to be removed.
|
||||
template<typename It, IteratorPairWith<It> EndIt, typename ToIndex = decltype (*declval<It>()) (*)(It const&)>
|
||||
void remove_all(It&& it, EndIt const& end, ToIndex const& to_index = [](It const& it) -> decltype(auto) { return *it; })
|
||||
{
|
||||
if (!(it != end))
|
||||
return;
|
||||
size_t write_index = to_index(it);
|
||||
VERIFY(write_index < m_size);
|
||||
raw_at(write_index).~StorageType();
|
||||
++it;
|
||||
size_t next_remove_index = it != end ? to_index(it) : m_size;
|
||||
for (auto read_index = write_index + 1; read_index < m_size; ++read_index) {
|
||||
if (read_index == next_remove_index) {
|
||||
raw_at(read_index).~StorageType();
|
||||
++it;
|
||||
next_remove_index = it != end ? to_index(it) : m_size;
|
||||
} else {
|
||||
if constexpr (Traits<StorageType>::is_trivial()) {
|
||||
__builtin_memcpy(slot(write_index), slot(read_index), sizeof(StorageType));
|
||||
} else {
|
||||
new (slot(write_index)) StorageType(move(raw_at(read_index)));
|
||||
raw_at(read_index).~StorageType();
|
||||
}
|
||||
++write_index;
|
||||
}
|
||||
}
|
||||
|
||||
VERIFY(!(it != end));
|
||||
m_size = write_index;
|
||||
update_metadata();
|
||||
}
|
||||
|
||||
template<IterableContainer Is, typename ToIndex = decltype (*declval<Is>().begin()) (*)(decltype(declval<Is>().begin()) const&)>
|
||||
void remove_all(Is&& is, ToIndex const& to_index = [](auto const& it) -> decltype(auto) { return *it; })
|
||||
{
|
||||
remove_all(is.begin(), is.end(), to_index);
|
||||
}
|
||||
|
||||
template<typename TUnaryPredicate>
|
||||
bool remove_first_matching(TUnaryPredicate const& predicate)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -643,6 +643,57 @@ static bool is_inline_element(auto& el, auto& vector)
|
|||
\
|
||||
for (auto& el : v) \
|
||||
EXPECT(is_inline_element(el, v)); \
|
||||
} \
|
||||
TEST_CASE(Vector##_remove_all) \
|
||||
{ \
|
||||
{ \
|
||||
Vector<int> v0 { 1, 2, 3, 2, 4, 2, 5 }; \
|
||||
Array indices { 1, 4, 6 }; \
|
||||
v0.remove_all(indices); \
|
||||
EXPECT_EQ(v0.size(), 4u); \
|
||||
EXPECT_EQ(v0[0], 1); \
|
||||
EXPECT_EQ(v0[1], 3); \
|
||||
EXPECT_EQ(v0[2], 2); \
|
||||
EXPECT_EQ(v0[3], 2); \
|
||||
} \
|
||||
{ \
|
||||
Vector<int> v1 { 1, 2, 3, 4, 5 }; \
|
||||
Array indices { 0, 1, 2, 3, 4 }; \
|
||||
v1.remove_all(indices); \
|
||||
EXPECT_EQ(v1.size(), 0u); \
|
||||
} \
|
||||
{ \
|
||||
Vector<int> v2 { 1, 2, 3, 4, 5 }; \
|
||||
Array<u32, 0> indices; \
|
||||
v2.remove_all(indices); \
|
||||
EXPECT_EQ(v2.size(), 5u); \
|
||||
EXPECT_EQ(v2[0], 1); \
|
||||
EXPECT_EQ(v2[1], 2); \
|
||||
EXPECT_EQ(v2[2], 3); \
|
||||
EXPECT_EQ(v2[3], 4); \
|
||||
EXPECT_EQ(v2[4], 5); \
|
||||
} \
|
||||
{ \
|
||||
Vector<int> v3; \
|
||||
Array<u32, 0> indices; \
|
||||
v3.remove_all(indices); \
|
||||
EXPECT_EQ(v3.size(), 0u); \
|
||||
} \
|
||||
/* One more test with a nonstandard iterator deref function */ \
|
||||
{ \
|
||||
Vector<int> v4 { 1, 2, 3, 2, 4, 2, 5 }; \
|
||||
struct IndexWrapper { \
|
||||
size_t index; \
|
||||
size_t const& operator*() const { return index; } \
|
||||
}; \
|
||||
Array<IndexWrapper, 3> indices { IndexWrapper { 1 }, IndexWrapper { 4 }, IndexWrapper { 6 } }; \
|
||||
v4.remove_all(indices, [](auto const& it) -> size_t { return **it; }); \
|
||||
EXPECT_EQ(v4.size(), 4u); \
|
||||
EXPECT_EQ(v4[0], 1); \
|
||||
EXPECT_EQ(v4[1], 3); \
|
||||
EXPECT_EQ(v4[2], 2); \
|
||||
EXPECT_EQ(v4[3], 2); \
|
||||
} \
|
||||
}
|
||||
|
||||
DECLARE_TESTS_FOR_VEC(Vector)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user