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:
Diffstat (limited to 'source/blender/blenlib/BLI_virtual_list_ref.h')
-rw-r--r--source/blender/blenlib/BLI_virtual_list_ref.h187
1 files changed, 187 insertions, 0 deletions
diff --git a/source/blender/blenlib/BLI_virtual_list_ref.h b/source/blender/blenlib/BLI_virtual_list_ref.h
new file mode 100644
index 00000000000..3f9cfab1f4d
--- /dev/null
+++ b/source/blender/blenlib/BLI_virtual_list_ref.h
@@ -0,0 +1,187 @@
+#ifndef __BLI_VIRTUAL_LIST_REF_H__
+#define __BLI_VIRTUAL_LIST_REF_H__
+
+#include "BLI_array_ref.h"
+
+#include <climits>
+
+namespace BLI {
+
+template<typename T> class VirtualListRef {
+ private:
+ enum Category {
+ Single,
+ FullArray,
+ FullPointerArray,
+ RepeatedArray,
+ };
+
+ uint m_virtual_size;
+ Category m_category;
+
+ union {
+ struct {
+ const T *data;
+ } single;
+ struct {
+ const T *data;
+ } full_array;
+ struct {
+ const T *const *data;
+ } full_pointer_array;
+ struct {
+ const T *data;
+ uint real_size;
+ } repeated_array;
+ } m_data;
+
+ public:
+ VirtualListRef()
+ {
+ m_virtual_size = 0;
+ m_category = Category::FullArray;
+ m_data.single.data = nullptr;
+ }
+
+ static VirtualListRef FromSingle(const T *data, uint virtual_size)
+ {
+ VirtualListRef list;
+ list.m_virtual_size = virtual_size;
+ list.m_category = Category::Single;
+ list.m_data.single.data = data;
+ return list;
+ }
+
+ static VirtualListRef FromSingle_MaxSize(const T *data)
+ {
+ return VirtualListRef::FromSingle(data, UINT_MAX);
+ }
+
+ static VirtualListRef FromFullArray(const T *data, uint size)
+ {
+ VirtualListRef list;
+ list.m_virtual_size = size;
+ list.m_category = Category::FullArray;
+ list.m_data.full_array.data = data;
+ return list;
+ }
+
+ static VirtualListRef FromFullArray(ArrayRef<T> array)
+ {
+ return VirtualListRef::FromFullArray(array.begin(), array.size());
+ }
+
+ static VirtualListRef FromFullPointerArray(const T *const *data, uint size)
+ {
+ VirtualListRef list;
+ list.m_virtual_size = size;
+ list.m_category = Category::FullPointerArray;
+ list.m_data.full_pointer_array.data = data;
+ return list;
+ }
+
+ static VirtualListRef FromFullPointerArray(ArrayRef<const T *> data)
+ {
+ return VirtualListRef::FromFullPointerArray(data.begin(), data.size());
+ }
+
+ static VirtualListRef FromRepeatedArray(const T *data, uint real_size, uint virtual_size)
+ {
+ BLI_assert(virtual_size == 0 || real_size > 0);
+
+ VirtualListRef list;
+ list.m_virtual_size = virtual_size;
+ list.m_category = Category::RepeatedArray;
+ list.m_data.repeated_array.data = data;
+ list.m_data.repeated_array.real_size = real_size;
+ return list;
+ }
+
+ static VirtualListRef FromRepeatedArray(ArrayRef<T> array, uint virtual_size)
+ {
+ return VirtualListRef::FromRepeatedArray(array.begin(), array.size(), virtual_size);
+ }
+
+ bool all_equal(ArrayRef<uint> indices) const
+ {
+ if (indices.size() == 0) {
+ return true;
+ }
+ if (this->is_single_element()) {
+ return true;
+ }
+
+ const T &first_value = (*this)[indices.first()];
+ for (uint i : indices.drop_front(1)) {
+ if (first_value != (*this)[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ const T &operator[](uint index) const
+ {
+ BLI_assert(index < m_virtual_size);
+ switch (m_category) {
+ case Category::Single:
+ return *m_data.single.data;
+ case Category::FullArray:
+ return m_data.full_array.data[index];
+ case Category::FullPointerArray:
+ return *m_data.full_pointer_array.data[index];
+ case Category::RepeatedArray:
+ uint real_index = index % m_data.repeated_array.real_size;
+ return m_data.repeated_array.data[real_index];
+ }
+ BLI_assert(false);
+ return *m_data.single.data;
+ }
+
+ uint size() const
+ {
+ return m_virtual_size;
+ }
+
+ bool is_non_single_full_array() const
+ {
+ return m_category == Category::FullArray && m_virtual_size > 1;
+ }
+
+ ArrayRef<T> as_full_array() const
+ {
+ BLI_assert(m_category == Category::FullArray);
+ return ArrayRef<T>(m_data.full_array.data, m_virtual_size);
+ }
+
+ const T &as_single_element() const
+ {
+ BLI_assert(this->is_single_element());
+ return (*this)[0];
+ }
+
+ bool is_single_element() const
+ {
+ switch (m_category) {
+ case Category::Single:
+ return true;
+ case Category::FullArray:
+ return m_virtual_size == 1;
+ case Category::FullPointerArray:
+ return m_virtual_size == 1;
+ case Category::RepeatedArray:
+ return m_data.repeated_array.real_size == 1;
+ }
+ BLI_assert(false);
+ return false;
+ }
+
+ IndexRange index_range() const
+ {
+ return IndexRange(m_virtual_size);
+ }
+};
+
+} // namespace BLI
+
+#endif /* __BLI_VIRTUAL_LIST_REF_H__ */