From 0e50b6529cf8b43d4ff7a738bf201e6058ca5ba6 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Wed, 26 Aug 2020 10:52:35 +0200 Subject: [PATCH] BLI: support removing multiple elements from a vector --- source/blender/blenlib/BLI_vector.hh | 21 ++++++++++++ .../blender/blenlib/tests/BLI_vector_test.cc | 32 +++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/source/blender/blenlib/BLI_vector.hh b/source/blender/blenlib/BLI_vector.hh index 392b6cd9f47..3c90e1ab755 100644 --- a/source/blender/blenlib/BLI_vector.hh +++ b/source/blender/blenlib/BLI_vector.hh @@ -741,6 +741,27 @@ class Vector { UPDATE_VECTOR_SIZE(this); } + /** + * Remove a contiguous chunk of elements and move all values coming after it towards the front. + * This takes O(n) time. + * + * This is similar to std::vector::erase. + */ + void remove(const int64_t start_index, const int64_t amount) + { + const int64_t old_size = this->size(); + BLI_assert(start_index >= 0); + BLI_assert(amount >= 0); + BLI_assert(start_index + amount <= old_size); + const int64_t move_amount = old_size - start_index - amount; + for (int64_t i = 0; i < move_amount; i++) { + begin_[start_index + i] = std::move(begin_[start_index + amount + i]); + } + destruct_n(end_ - amount, amount); + end_ -= amount; + UPDATE_VECTOR_SIZE(this); + } + /** * Do a linear search to find the value in the vector. * When found, return the first index, otherwise return -1. diff --git a/source/blender/blenlib/tests/BLI_vector_test.cc b/source/blender/blenlib/tests/BLI_vector_test.cc index 056a7aa3924..6dfab0d9e6f 100644 --- a/source/blender/blenlib/tests/BLI_vector_test.cc +++ b/source/blender/blenlib/tests/BLI_vector_test.cc @@ -793,4 +793,36 @@ TEST(vector, RemoveExceptions) EXPECT_EQ(vec.size(), 10); } +TEST(vector, RemoveChunk) +{ + Vector vec = {2, 3, 4, 5, 6, 7, 8}; + EXPECT_EQ(vec.size(), 7); + vec.remove(2, 4); + EXPECT_EQ(vec.size(), 3); + EXPECT_EQ(vec[0], 2); + EXPECT_EQ(vec[1], 3); + EXPECT_EQ(vec[2], 8); + vec.remove(0, 1); + EXPECT_EQ(vec.size(), 2); + EXPECT_EQ(vec[0], 3); + EXPECT_EQ(vec[1], 8); + vec.remove(1, 1); + EXPECT_EQ(vec.size(), 1); + EXPECT_EQ(vec[0], 3); + vec.remove(0, 1); + EXPECT_EQ(vec.size(), 0); + vec.remove(0, 0); + EXPECT_EQ(vec.size(), 0); +} + +TEST(vector, RemoveChunkExceptitons) +{ + Vector vec(10); + vec.remove(1, 3); + EXPECT_EQ(vec.size(), 7); + vec[5].throw_during_move = true; + EXPECT_ANY_THROW({ vec.remove(2, 3); }); + EXPECT_EQ(vec.size(), 7); +} + } // namespace blender::tests