Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Lucke <jacques@blender.org>2020-08-14 14:16:44 +0300
committerJacques Lucke <jacques@blender.org>2020-08-14 14:16:44 +0300
commitcc6c52768a9e6d5c82f35e953a6e53ece76d3a78 (patch)
tree2318e47733e2c63eda60011b22797bad22022cbd /source/blender/blenlib/BLI_vector.hh
parent2d653364086d62cc9b503724c962cc466ad3e4b4 (diff)
BLI: add reverse iterators, iterator constructor and Vector.insert/prepend
The new reverse iterators behave as the reverse iterators for contains from the standard library. Have a look at the tests to see how to use them. Using them will hopefully become easier with ranges in C++20. A Vector can now be constructed from two iterators, which is very common in the standard library. New Vector.insert methods allow adding elements in the middle of a vector. These methods should not be used often in practice, because they has a linear running time. New Vector.prepend methods allow adding elements to the beginning of a vector. These methods are O(n) as well.
Diffstat (limited to 'source/blender/blenlib/BLI_vector.hh')
-rw-r--r--source/blender/blenlib/BLI_vector.hh108
1 files changed, 98 insertions, 10 deletions
diff --git a/source/blender/blenlib/BLI_vector.hh b/source/blender/blenlib/BLI_vector.hh
index 48110ef2814..74ce8dd42e7 100644
--- a/source/blender/blenlib/BLI_vector.hh
+++ b/source/blender/blenlib/BLI_vector.hh
@@ -178,17 +178,15 @@ class Vector {
{
}
- /**
- * Create a vector from any container. It must be possible to use the container in a
- * range-for loop.
- */
- template<typename ContainerT> static Vector FromContainer(const ContainerT &container)
- {
- Vector vector;
- for (const auto &value : container) {
- vector.append(value);
+ template<typename InputIt,
+ /* This constructor should not be called with e.g. Vector(3, 10), because that is
+ expected to produce the vector (10, 10, 10). */
+ typename std::enable_if_t<!std::is_convertible_v<InputIt, int>> * = nullptr>
+ Vector(InputIt first, InputIt last, Allocator allocator = {}) : Vector(std::move(allocator))
+ {
+ for (InputIt current = first; current != last; ++current) {
+ this->append(*current);
}
- return vector;
}
/**
@@ -560,6 +558,78 @@ class Vector {
UPDATE_VECTOR_SIZE(this);
}
+ template<typename InputIt> void extend(InputIt first, InputIt last)
+ {
+ this->insert(this->end(), first, last);
+ }
+
+ /**
+ * Insert elements into the vector at the specified position. This has a running time of O(n)
+ * where n is the number of values that have to be moved. Undefined behavior is invoked when the
+ * insert position is out of bounds.
+ */
+ void insert(const int64_t insert_index, const T &value)
+ {
+ this->insert(insert_index, Span<T>(&value, 1));
+ }
+ void insert(const int64_t insert_index, T &&value)
+ {
+ this->insert(
+ insert_index, std::make_move_iterator(&value), std::make_move_iterator(&value + 1));
+ }
+ void insert(const int64_t insert_index, Span<T> array)
+ {
+ this->insert(begin_ + insert_index, array.begin(), array.end());
+ }
+ template<typename InputIt> void insert(const T *insert_position, InputIt first, InputIt last)
+ {
+ const int64_t insert_index = insert_position - begin_;
+ this->insert(insert_index, first, last);
+ }
+ template<typename InputIt> void insert(const int64_t insert_index, InputIt first, InputIt last)
+ {
+ BLI_assert(insert_index >= 0);
+ BLI_assert(insert_index <= this->size());
+
+ const int64_t insert_amount = std::distance(first, last);
+ const int64_t old_size = this->size();
+ const int64_t new_size = old_size + insert_amount;
+ const int64_t move_amount = old_size - insert_index;
+
+ this->reserve(new_size);
+ for (int64_t i = 0; i < move_amount; i++) {
+ const int64_t src_index = insert_index + move_amount - i - 1;
+ const int64_t dst_index = new_size - i - 1;
+ new (static_cast<void *>(begin_ + dst_index)) T(std::move(begin_[src_index]));
+ begin_[src_index].~T();
+ }
+
+ std::uninitialized_copy_n(first, insert_amount, begin_ + insert_index);
+ end_ = begin_ + new_size;
+ UPDATE_VECTOR_SIZE(this);
+ }
+
+ /**
+ * Insert values at the beginning of the vector. The has to move all the other elements, so it
+ * has a linear running time.
+ */
+ void prepend(const T &&value)
+ {
+ this->insert(0, value);
+ }
+ void prepend(T &&value)
+ {
+ this->insert(0, std::move(value));
+ }
+ void prepend(Span<T> values)
+ {
+ this->insert(0, values);
+ }
+ template<typename InputIt> void prepend(InputIt first, InputIt last)
+ {
+ this->insert(0, first, last);
+ }
+
/**
* Return a reference to the last element in the vector.
* This invokes undefined behavior when the vector is empty.
@@ -746,6 +816,24 @@ class Vector {
return end_;
}
+ std::reverse_iterator<T *> rbegin()
+ {
+ return std::reverse_iterator<T *>(this->end());
+ }
+ std::reverse_iterator<T *> rend()
+ {
+ return std::reverse_iterator<T *>(this->begin());
+ }
+
+ std::reverse_iterator<const T *> rbegin() const
+ {
+ return std::reverse_iterator<T *>(this->end());
+ }
+ std::reverse_iterator<const T *> rend() const
+ {
+ return std::reverse_iterator<T *>(this->begin());
+ }
+
/**
* Get the current capacity of the vector, i.e. the maximum number of elements the vector can
* hold, before it has to reallocate.