[Bf-blender-cvs] [6223385043d] master: Functions: Various improvements to the spans and generic data structures
Jacques Lucke
noreply at git.blender.org
Mon Jun 22 15:54:11 CEST 2020
Commit: 6223385043ddc93beaa8f092dfd31a2208b8e961
Author: Jacques Lucke
Date: Mon Jun 22 15:48:08 2020 +0200
Branches: master
https://developer.blender.org/rB6223385043ddc93beaa8f092dfd31a2208b8e961
Functions: Various improvements to the spans and generic data structures
Most of this code is covered by unit tests.
===================================================================
M source/blender/functions/FN_array_spans.hh
M source/blender/functions/FN_cpp_type.hh
M source/blender/functions/FN_generic_vector_array.hh
M source/blender/functions/FN_multi_function_data_type.hh
M source/blender/functions/FN_multi_function_param_type.hh
M source/blender/functions/FN_multi_function_params.hh
M source/blender/functions/FN_multi_function_signature.hh
M source/blender/functions/FN_spans.hh
M tests/gtests/functions/FN_array_spans_test.cc
M tests/gtests/functions/FN_generic_vector_array_test.cc
M tests/gtests/functions/FN_spans_test.cc
===================================================================
diff --git a/source/blender/functions/FN_array_spans.hh b/source/blender/functions/FN_array_spans.hh
index ca818ad6b11..fac2ef42c9d 100644
--- a/source/blender/functions/FN_array_spans.hh
+++ b/source/blender/functions/FN_array_spans.hh
@@ -30,22 +30,18 @@ namespace blender {
namespace fn {
/**
- * A virtual array span. Every element of this span contains a virtual span. So it behaves like a
- * blender::Span, but might not be backed up by an actual array.
+ * Depending on the use case, the referenced data might have a different structure. More
+ * categories can be added when necessary.
*/
-template<typename T> class VArraySpan {
- private:
- /**
- * Depending on the use case, the referenced data might have a different structure. More
- * categories can be added when necessary.
- */
- enum Category {
- SingleArray,
- StartsAndSizes,
- };
+enum class VArraySpanCategory {
+ SingleArray,
+ StartsAndSizes,
+};
+template<typename T> class VArraySpanBase {
+ protected:
uint m_virtual_size;
- Category m_category;
+ VArraySpanCategory m_category;
union {
struct {
@@ -59,50 +55,77 @@ template<typename T> class VArraySpan {
} m_data;
public:
- VArraySpan()
+ bool is_single_array() const
{
- m_virtual_size = 0;
- m_category = StartsAndSizes;
- m_data.starts_and_sizes.starts = nullptr;
- m_data.starts_and_sizes.sizes = nullptr;
+ switch (m_category) {
+ case VArraySpanCategory::SingleArray:
+ return true;
+ case VArraySpanCategory::StartsAndSizes:
+ return m_virtual_size == 1;
+ }
+ BLI_assert(false);
+ return false;
}
- VArraySpan(Span<T> span, uint virtual_size)
+ bool is_empty() const
{
- m_virtual_size = virtual_size;
- m_category = SingleArray;
- m_data.single_array.start = span.data();
- m_data.single_array.size = span.size();
+ return this->m_virtual_size == 0;
}
- VArraySpan(Span<const T *> starts, Span<uint> sizes)
+ uint size() const
{
- BLI_assert(starts.size() == sizes.size());
- m_virtual_size = starts.size();
- m_category = StartsAndSizes;
- m_data.starts_and_sizes.starts = starts.begin();
- m_data.starts_and_sizes.sizes = sizes.begin();
+ return this->m_virtual_size;
}
+};
- bool is_empty() const
+/**
+ * A virtual array span. Every element of this span contains a virtual span. So it behaves like
+ * a blender::Span, but might not be backed up by an actual array.
+ */
+template<typename T> class VArraySpan : public VArraySpanBase<T> {
+ private:
+ friend class GVArraySpan;
+
+ VArraySpan(const VArraySpanBase<void> &other)
{
- return m_virtual_size == 0;
+ memcpy(this, &other, sizeof(VArraySpanBase<void>));
}
- uint size() const
+ public:
+ VArraySpan()
+ {
+ this->m_virtual_size = 0;
+ this->m_category = VArraySpanCategory::StartsAndSizes;
+ this->m_data.starts_and_sizes.starts = nullptr;
+ this->m_data.starts_and_sizes.sizes = nullptr;
+ }
+
+ VArraySpan(Span<T> span, uint virtual_size)
{
- return m_virtual_size;
+ this->m_virtual_size = virtual_size;
+ this->m_category = VArraySpanCategory::SingleArray;
+ this->m_data.single_array.start = span.data();
+ this->m_data.single_array.size = span.size();
+ }
+
+ VArraySpan(Span<const T *> starts, Span<uint> sizes)
+ {
+ BLI_assert(starts.size() == sizes.size());
+ this->m_virtual_size = starts.size();
+ this->m_category = VArraySpanCategory::StartsAndSizes;
+ this->m_data.starts_and_sizes.starts = starts.begin();
+ this->m_data.starts_and_sizes.sizes = sizes.begin();
}
VSpan<T> operator[](uint index) const
{
- BLI_assert(index < m_virtual_size);
- switch (m_category) {
- case SingleArray:
- return VSpan<T>(Span<T>(m_data.single_array.start, m_data.single_array.size));
- case StartsAndSizes:
- return VSpan<T>(
- Span<T>(m_data.starts_and_sizes.starts[index], m_data.starts_and_sizes.sizes[index]));
+ BLI_assert(index < this->m_virtual_size);
+ switch (this->m_category) {
+ case VArraySpanCategory::SingleArray:
+ return VSpan<T>(Span<T>(this->m_data.single_array.start, this->m_data.single_array.size));
+ case VArraySpanCategory::StartsAndSizes:
+ return VSpan<T>(Span<T>(this->m_data.starts_and_sizes.starts[index],
+ this->m_data.starts_and_sizes.sizes[index]));
}
BLI_assert(false);
return {};
@@ -113,99 +136,65 @@ template<typename T> class VArraySpan {
* A generic virtual array span. It's just like a VArraySpan, but the type is only known at
* run-time.
*/
-class GVArraySpan {
+class GVArraySpan : public VArraySpanBase<void> {
private:
- /**
- * Depending on the use case, the referenced data might have a different structure. More
- * categories can be added when necessary.
- */
- enum Category {
- SingleArray,
- StartsAndSizes,
- };
-
const CPPType *m_type;
- uint m_virtual_size;
- Category m_category;
-
- union {
- struct {
- const void *values;
- uint size;
- } single_array;
- struct {
- const void *const *starts;
- const uint *sizes;
- } starts_and_sizes;
- } m_data;
GVArraySpan() = default;
public:
GVArraySpan(const CPPType &type)
{
- m_type = &type;
- m_virtual_size = 0;
- m_category = StartsAndSizes;
- m_data.starts_and_sizes.starts = nullptr;
- m_data.starts_and_sizes.sizes = nullptr;
+ this->m_type = &type;
+ this->m_virtual_size = 0;
+ this->m_category = VArraySpanCategory::StartsAndSizes;
+ this->m_data.starts_and_sizes.starts = nullptr;
+ this->m_data.starts_and_sizes.sizes = nullptr;
}
GVArraySpan(GSpan array, uint virtual_size)
{
- m_type = &array.type();
- m_virtual_size = virtual_size;
- m_category = SingleArray;
- m_data.single_array.values = array.buffer();
- m_data.single_array.size = array.size();
+ this->m_type = &array.type();
+ this->m_virtual_size = virtual_size;
+ this->m_category = VArraySpanCategory::SingleArray;
+ this->m_data.single_array.start = array.buffer();
+ this->m_data.single_array.size = array.size();
}
GVArraySpan(const CPPType &type, Span<const void *> starts, Span<uint> sizes)
{
BLI_assert(starts.size() == sizes.size());
- m_type = &type;
- m_virtual_size = starts.size();
- m_category = StartsAndSizes;
- m_data.starts_and_sizes.starts = starts.begin();
- m_data.starts_and_sizes.sizes = sizes.begin();
- }
-
- bool is_empty() const
- {
- return m_virtual_size == 0;
+ this->m_type = &type;
+ this->m_virtual_size = starts.size();
+ this->m_category = VArraySpanCategory::StartsAndSizes;
+ this->m_data.starts_and_sizes.starts = (void **)starts.begin();
+ this->m_data.starts_and_sizes.sizes = sizes.begin();
}
- uint size() const
+ template<typename T> GVArraySpan(VArraySpan<T> other)
{
- return m_virtual_size;
+ this->m_type = &CPPType::get<T>();
+ memcpy(this, &other, sizeof(VArraySpanBase<void>));
}
const CPPType &type() const
{
- return *m_type;
+ return *this->m_type;
}
template<typename T> VArraySpan<T> typed() const
{
BLI_assert(CPPType::get<T>() == *m_type);
- switch (m_category) {
- case SingleArray:
- return VArraySpan<T>(
- Span<T>((const T *)m_data.single_array.values, m_data.single_array.size));
- case StartsAndSizes:
- return VArraySpan<T>(
- Span<const T *>((const T *const *)m_data.starts_and_sizes.starts, m_virtual_size),
- Span<uint>(m_data.starts_and_sizes.sizes, m_virtual_size));
- }
+ return VArraySpan<T>(*this);
}
GVSpan operator[](uint index) const
{
BLI_assert(index < m_virtual_size);
switch (m_category) {
- case SingleArray:
- return GVSpan(GSpan(*m_type, m_data.single_array.values, m_data.single_array.size));
- case StartsAndSizes:
+ case VArraySpanCategory::SingleArray:
+ return GVSpan(GSpan(*m_type, m_data.single_array.start, m_data.single_array.size));
+ case VArraySpanCategory::StartsAndSizes:
return GVSpan(GSpan(
*m_type, m_data.starts_and_sizes.starts[index], m_data.starts_and_sizes.sizes[index]));
}
diff --git a/source/blender/functions/FN_cpp_type.hh b/source/blender/functions/FN_cpp_type.hh
index df5218ed5ba..c6e440251ee 100644
--- a/source/blender/functions/FN_cpp_type.hh
+++ b/source/blender/functions/FN_cpp_type.hh
@@ -725,6 +725,8 @@ static std::unique_ptr<const CPPType> create_cpp_type(StringRef name, const T &d
const blender::fn::CPPType &CPPType_##IDENTIFIER = *CPPTYPE_##IDENTIFIER##_owner; \
template<> const blender::fn::CPPType &blender::fn::CPPType::get<TYPE_NAME>() \
{ \
+ /* This can happen when trying to access a CPPType during static storage initialization. */ \
+ BLI_assert(CPPTYPE_##IDENTIFIER##_owner.get() != nullptr); \
return CPPType_##IDENTIFIER; \
}
diff --git a/source/blender/functions/FN_generic_vector_array.hh b/source/blender/functions/FN_generic_vector_array.hh
index 90c0fbad136..1c8f74f2abe 100644
--- a/source/blender/functions/FN_generic_vector_array.hh
+++ b/source/blender/functions/FN_generic_vector_array.hh
@@ -119,6 +119,23 @@ class GVectorArray : NonCopyable, NonMovable {
m_lengths[index]++;
}
+ void extend(uint index, GVSpan span)
+ {
+ BLI_assert(m_type == span.type());
+ for (uint i = 0; i < span.size(); i++) {
+ this->append(index, span[i]);
+ }
+ }
+
+ void extend(IndexMask mask, GVArraySpan array_span)
+ {
+ BLI_assert(m_type == array_span.type());
+ BLI_assert(mask.min_array_size() <= array_span.size());
+ for (uint i : mask) {
+ this->extend(i, array_span[i]);
+ }
+ }
+
GMutableSpan operator[](uint index)
{
BLI_assert(index < m_starts.size());
@@ -158,6 +175,16 @@ template<typename T> class GVectorArrayRef {
m_vector_array->append(index, &value);
}
+ void extend(uint index, Span<T> values)
+ {
+ m_vector_array->extend(index, values);
+ }
+
+ void extend(uint index, VSpan<T> values)
+ {
+ m_vector_array->extend(index, GVSpan(values));
+ }
+
Muta
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list