[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