diff options
-rw-r--r-- | source/blender/blenlib/BLI_generic_span.hh | 64 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_generic_virtual_array.hh | 4 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_virtual_array.hh | 23 | ||||
-rw-r--r-- | source/blender/blenlib/intern/generic_virtual_array.cc | 32 | ||||
-rw-r--r-- | source/blender/blenlib/tests/BLI_virtual_array_test.cc | 33 |
5 files changed, 135 insertions, 21 deletions
diff --git a/source/blender/blenlib/BLI_generic_span.hh b/source/blender/blenlib/BLI_generic_span.hh index 4c0bfc83ba8..0a40201634a 100644 --- a/source/blender/blenlib/BLI_generic_span.hh +++ b/source/blender/blenlib/BLI_generic_span.hh @@ -16,20 +16,30 @@ namespace blender { */ class GSpan { protected: - const CPPType *type_; - const void *data_; - int64_t size_; + const CPPType *type_ = nullptr; + const void *data_ = nullptr; + int64_t size_ = 0; public: - GSpan(const CPPType &type, const void *buffer, int64_t size) - : type_(&type), data_(buffer), size_(size) + GSpan() = default; + + GSpan(const CPPType *type, const void *buffer, int64_t size) + : type_(type), data_(buffer), size_(size) { BLI_assert(size >= 0); BLI_assert(buffer != nullptr || size == 0); - BLI_assert(type.pointer_has_valid_alignment(buffer)); + BLI_assert(type->pointer_has_valid_alignment(buffer)); + } + + GSpan(const CPPType &type, const void *buffer, int64_t size) : GSpan(&type, buffer, size) + { + } + + GSpan(const CPPType &type) : type_(&type) + { } - GSpan(const CPPType &type) : GSpan(type, nullptr, 0) + GSpan(const CPPType *type) : type_(type) { } @@ -41,9 +51,15 @@ class GSpan { const CPPType &type() const { + BLI_assert(type_ != nullptr); return *type_; } + const CPPType *type_ptr() const + { + return type_; + } + bool is_empty() const { return size_ == 0; @@ -76,7 +92,7 @@ class GSpan { BLI_assert(start >= 0); BLI_assert(size >= 0); const int64_t new_size = std::max<int64_t>(0, std::min(size, size_ - start)); - return GSpan(*type_, POINTER_OFFSET(data_, type_->size() * start), new_size); + return GSpan(type_, POINTER_OFFSET(data_, type_->size() * start), new_size); } GSpan slice(const IndexRange range) const @@ -91,20 +107,30 @@ class GSpan { */ class GMutableSpan { protected: - const CPPType *type_; - void *data_; - int64_t size_; + const CPPType *type_ = nullptr; + void *data_ = nullptr; + int64_t size_ = 0; public: - GMutableSpan(const CPPType &type, void *buffer, int64_t size) - : type_(&type), data_(buffer), size_(size) + GMutableSpan() = default; + + GMutableSpan(const CPPType *type, void *buffer, int64_t size) + : type_(type), data_(buffer), size_(size) { BLI_assert(size >= 0); BLI_assert(buffer != nullptr || size == 0); - BLI_assert(type.pointer_has_valid_alignment(buffer)); + BLI_assert(type->pointer_has_valid_alignment(buffer)); + } + + GMutableSpan(const CPPType &type, void *buffer, int64_t size) : GMutableSpan(&type, buffer, size) + { + } + + GMutableSpan(const CPPType &type) : type_(&type) + { } - GMutableSpan(const CPPType &type) : GMutableSpan(type, nullptr, 0) + GMutableSpan(const CPPType *type) : type_(type) { } @@ -116,14 +142,20 @@ class GMutableSpan { operator GSpan() const { - return GSpan(*type_, data_, size_); + return GSpan(type_, data_, size_); } const CPPType &type() const { + BLI_assert(type_ != nullptr); return *type_; } + const CPPType *type_ptr() const + { + return type_; + } + bool is_empty() const { return size_ == 0; diff --git a/source/blender/blenlib/BLI_generic_virtual_array.hh b/source/blender/blenlib/BLI_generic_virtual_array.hh index 3526925c2e2..43ca16a894f 100644 --- a/source/blender/blenlib/BLI_generic_virtual_array.hh +++ b/source/blender/blenlib/BLI_generic_virtual_array.hh @@ -267,6 +267,7 @@ class GVArraySpan : public GSpan { void *owned_data_ = nullptr; public: + GVArraySpan(); GVArraySpan(GVArray varray); GVArraySpan(GVArraySpan &&other); ~GVArraySpan(); @@ -282,11 +283,14 @@ class GMutableVArraySpan : public GMutableSpan, NonCopyable, NonMovable { bool show_not_saved_warning_ = true; public: + GMutableVArraySpan(); GMutableVArraySpan(GVMutableArray varray, bool copy_values_to_span = true); GMutableVArraySpan(GMutableVArraySpan &&other); ~GMutableVArraySpan(); GMutableVArraySpan &operator=(GMutableVArraySpan &&other); + const GVMutableArray &varray() const; + void save(); void disable_not_applied_warning(); }; diff --git a/source/blender/blenlib/BLI_virtual_array.hh b/source/blender/blenlib/BLI_virtual_array.hh index 84f6223580a..56b2f9f6c6f 100644 --- a/source/blender/blenlib/BLI_virtual_array.hh +++ b/source/blender/blenlib/BLI_virtual_array.hh @@ -1130,6 +1130,9 @@ template<typename T> class VArraySpan final : public Span<T> { VArraySpan(VArray<T> varray) : Span<T>(), varray_(std::move(varray)) { + if (!varray_) { + return; + } this->size_ = varray_.size(); const CommonVArrayInfo info = varray_.common_info(); if (info.type == CommonVArrayInfo::Type::Span) { @@ -1146,6 +1149,9 @@ template<typename T> class VArraySpan final : public Span<T> { VArraySpan(VArraySpan &&other) : varray_(std::move(other.varray_)), owned_data_(std::move(other.owned_data_)) { + if (!varray_) { + return; + } this->size_ = varray_.size(); const CommonVArrayInfo info = varray_.common_info(); if (info.type == CommonVArrayInfo::Type::Span) { @@ -1184,11 +1190,17 @@ template<typename T> class MutableVArraySpan final : public MutableSpan<T> { bool show_not_saved_warning_ = true; public: + MutableVArraySpan() = default; + /* Create a span for any virtual array. This is cheap when the virtual array is a span itself. If * not, a new array has to be allocated as a wrapper for the underlying virtual array. */ MutableVArraySpan(VMutableArray<T> varray, const bool copy_values_to_span = true) : MutableSpan<T>(), varray_(std::move(varray)) { + if (!varray_) { + return; + } + this->size_ = varray_.size(); const CommonVArrayInfo info = varray_.common_info(); if (info.type == CommonVArrayInfo::Type::Span) { @@ -1212,10 +1224,14 @@ template<typename T> class MutableVArraySpan final : public MutableSpan<T> { owned_data_(std::move(owned_data_)), show_not_saved_warning_(other.show_not_saved_warning_) { + if (!varray_) { + return; + } + this->size_ = varray_.size(); const CommonVArrayInfo info = varray_.common_info(); if (info.type == CommonVArrayInfo::Type::Span) { - this->data_ = reinterpret_cast<T *>(info.data); + this->data_ = static_cast<T *>(const_cast<void *>(info.data)); } else { this->data_ = owned_data_.data(); @@ -1245,6 +1261,11 @@ template<typename T> class MutableVArraySpan final : public MutableSpan<T> { return *this; } + const VMutableArray<T> &varray() const + { + return varray_; + } + /* Write back all values from a temporary allocated array to the underlying virtual array. */ void save() { diff --git a/source/blender/blenlib/intern/generic_virtual_array.cc b/source/blender/blenlib/intern/generic_virtual_array.cc index 532c7b9b626..28bc66e8524 100644 --- a/source/blender/blenlib/intern/generic_virtual_array.cc +++ b/source/blender/blenlib/intern/generic_virtual_array.cc @@ -287,8 +287,15 @@ template<int BufferSize> class GVArrayImpl_For_SmallTrivialSingleValue : public /** \name #GVArraySpan * \{ */ -GVArraySpan::GVArraySpan(GVArray varray) : GSpan(varray.type()), varray_(std::move(varray)) +GVArraySpan::GVArraySpan() = default; + +GVArraySpan::GVArraySpan(GVArray varray) + : GSpan(varray ? &varray.type() : nullptr), varray_(std::move(varray)) { + if (!varray_) { + return; + } + size_ = varray_.size(); const CommonVArrayInfo info = varray_.common_info(); if (info.type == CommonVArrayInfo::Type::Span) { @@ -302,8 +309,12 @@ GVArraySpan::GVArraySpan(GVArray varray) : GSpan(varray.type()), varray_(std::mo } GVArraySpan::GVArraySpan(GVArraySpan &&other) - : GSpan(other.type()), varray_(std::move(other.varray_)), owned_data_(other.owned_data_) + : GSpan(other.type_ptr()), varray_(std::move(other.varray_)), owned_data_(other.owned_data_) { + if (!varray_) { + return; + } + size_ = varray_.size(); const CommonVArrayInfo info = varray_.common_info(); if (info.type == CommonVArrayInfo::Type::Span) { @@ -340,9 +351,14 @@ GVArraySpan &GVArraySpan::operator=(GVArraySpan &&other) /** \name #GMutableVArraySpan * \{ */ +GMutableVArraySpan::GMutableVArraySpan() = default; + GMutableVArraySpan::GMutableVArraySpan(GVMutableArray varray, const bool copy_values_to_span) - : GMutableSpan(varray.type()), varray_(std::move(varray)) + : GMutableSpan(varray ? &varray.type() : nullptr), varray_(std::move(varray)) { + if (!varray_) { + return; + } size_ = varray_.size(); const CommonVArrayInfo info = varray_.common_info(); if (info.type == CommonVArrayInfo::Type::Span) { @@ -361,11 +377,14 @@ GMutableVArraySpan::GMutableVArraySpan(GVMutableArray varray, const bool copy_va } GMutableVArraySpan::GMutableVArraySpan(GMutableVArraySpan &&other) - : GMutableSpan(other.type()), + : GMutableSpan(other.type_ptr()), varray_(std::move(other.varray_)), owned_data_(other.owned_data_), show_not_saved_warning_(other.show_not_saved_warning_) { + if (!varray_) { + return; + } size_ = varray_.size(); const CommonVArrayInfo info = varray_.common_info(); if (info.type == CommonVArrayInfo::Type::Span) { @@ -417,6 +436,11 @@ void GMutableVArraySpan::disable_not_applied_warning() show_not_saved_warning_ = false; } +const GVMutableArray &GMutableVArraySpan::varray() const +{ + return varray_; +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/blenlib/tests/BLI_virtual_array_test.cc b/source/blender/blenlib/tests/BLI_virtual_array_test.cc index c3c6d84ea42..14f5480f751 100644 --- a/source/blender/blenlib/tests/BLI_virtual_array_test.cc +++ b/source/blender/blenlib/tests/BLI_virtual_array_test.cc @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: Apache-2.0 */ #include "BLI_array.hh" +#include "BLI_generic_virtual_array.hh" #include "BLI_strict_flags.h" #include "BLI_vector.hh" #include "BLI_vector_set.hh" @@ -222,4 +223,36 @@ TEST(virtual_array, MaterializeCompressed) } } +TEST(virtual_array, EmptySpanWrapper) +{ + { + VArray<int> varray; + VArraySpan<int> span1 = varray; + EXPECT_TRUE(span1.is_empty()); + VArraySpan<int> span2 = std::move(span1); + EXPECT_TRUE(span2.is_empty()); + } + { + VMutableArray<int> varray; + MutableVArraySpan<int> span1 = varray; + EXPECT_TRUE(span1.is_empty()); + MutableVArraySpan<int> span2 = std::move(span1); + EXPECT_TRUE(span2.is_empty()); + } + { + GVArray varray; + GVArraySpan span1 = varray; + EXPECT_TRUE(span1.is_empty()); + GVArraySpan span2 = std::move(span1); + EXPECT_TRUE(span2.is_empty()); + } + { + GVMutableArray varray; + GMutableVArraySpan span1 = varray; + EXPECT_TRUE(span1.is_empty()); + GMutableVArraySpan span2 = std::move(span1); + EXPECT_TRUE(span2.is_empty()); + } +} + } // namespace blender::tests |