From 68cc982dcb7c1063a96f7ec9b7ccb95da4919d6b Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Mon, 10 Feb 2020 13:54:57 +0100 Subject: BLI: improve various C++ data structures The changes come from the `functions` branch, where I'm using these structures a lot. This also includes a new `BLI::Optional` type, which is similar to `std::Optional` which can be used when Blender starts using C++17. --- source/blender/blenlib/BLI_vector.h | 67 +++++++++++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 6 deletions(-) (limited to 'source/blender/blenlib/BLI_vector.h') diff --git a/source/blender/blenlib/BLI_vector.h b/source/blender/blenlib/BLI_vector.h index 5c03a896692..60251347795 100644 --- a/source/blender/blenlib/BLI_vector.h +++ b/source/blender/blenlib/BLI_vector.h @@ -49,7 +49,7 @@ template class Ve T *m_end; T *m_capacity_end; Allocator m_allocator; - char m_small_buffer[sizeof(T) * N]; + AlignedBuffer m_small_buffer; #ifndef NDEBUG /* Storing size in debug builds, because it makes debugging much easier sometimes. */ @@ -216,6 +216,16 @@ template class Ve return MutableArrayRef(m_begin, this->size()); } + ArrayRef as_ref() const + { + return *this; + } + + MutableArrayRef as_mutable_ref() + { + return *this; + } + Vector &operator=(const Vector &other) { if (this == &other) { @@ -234,6 +244,8 @@ template class Ve return *this; } + /* This can fail, when the vector is used to build a recursive data structure. + See https://youtu.be/7Qgd9B1KuMQ?t=840. */ this->~Vector(); new (this) Vector(std::move(other)); @@ -294,6 +306,20 @@ template class Ve this->append_unchecked(std::move(value)); } + uint append_and_get_index(const T &value) + { + uint index = this->size(); + this->append(value); + return index; + } + + void append_non_duplicates(const T &value) + { + if (!this->contains(value)) { + this->append(value); + } + } + void append_unchecked(const T &value) { BLI_assert(m_end < m_capacity_end); @@ -342,6 +368,13 @@ template class Ve this->extend_unchecked(start, amount); } + void extend_non_duplicates(ArrayRef array) + { + for (const T &value : array) { + this->append_non_duplicates(value); + } + } + void extend_unchecked(ArrayRef array) { this->extend_unchecked(array.begin(), array.size()); @@ -442,11 +475,17 @@ template class Ve UPDATE_VECTOR_SIZE(this); } + void remove_first_occurrence_and_reorder(const T &value) + { + uint index = this->index(value); + this->remove_and_reorder((uint)index); + } + /** * Do a linear search to find the value in the vector. * When found, return the first index, otherwise return -1. */ - int index(const T &value) const + int index_try(const T &value) const { for (T *current = m_begin; current != m_end; current++) { if (*current == value) { @@ -456,13 +495,24 @@ template class Ve return -1; } + /** + * Do a linear search to find the value in the vector. + * When found, return the first index, otherwise fail. + */ + uint index(const T &value) const + { + int index = this->index_try(value); + BLI_assert(index >= 0); + return (uint)index; + } + /** * Do a linear search to see of the value is in the vector. * Return true when it exists, otherwise false. */ bool contains(const T &value) const { - return this->index(value) != -1; + return this->index_try(value) != -1; } /** @@ -537,7 +587,7 @@ template class Ve private: T *small_buffer() const { - return (T *)m_small_buffer; + return (T *)m_small_buffer.ptr(); } bool is_small() const @@ -561,10 +611,11 @@ template class Ve /* Round up to the next power of two. Otherwise consecutive calls to grow can cause a * reallocation every time even though the min_capacity only increments. */ min_capacity = power_of_2_max_u(min_capacity); + uint size = this->size(); T *new_array = (T *)m_allocator.allocate_aligned( - min_capacity * (uint)sizeof(T), std::alignment_of::value, __func__); + min_capacity * (uint)sizeof(T), std::alignment_of::value, "grow BLI::Vector"); uninitialized_relocate_n(m_begin, size, new_array); if (!this->is_small()) { @@ -606,7 +657,11 @@ template class Ve #undef UPDATE_VECTOR_SIZE -template using TemporaryVector = Vector; +/** + * Use when the vector is used in the local scope of a function. It has a larger inline storage by + * default to make allocations less likely. + */ +template using ScopedVector = Vector; } /* namespace BLI */ -- cgit v1.2.3