Blender V4.3
BLI_virtual_array.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
28#include <optional>
29
30#include "BLI_any.hh"
31#include "BLI_array.hh"
33#include "BLI_index_mask.hh"
34#include "BLI_span.hh"
35
36namespace blender {
37
39class GVArray;
40class GVMutableArray;
41
47 enum class Type : uint8_t {
48 /* Is not one of the common special types below. */
49 Any,
50 Span,
51 Single,
52 };
53
55
57 bool may_have_ownership = true;
58
63 const void *data;
64
65 CommonVArrayInfo() = default;
66 CommonVArrayInfo(const Type _type, const bool _may_have_ownership, const void *_data)
67 : type(_type), may_have_ownership(_may_have_ownership), data(_data)
68 {
69 }
70};
71
76template<typename T> class VArrayImpl {
77 protected:
83
84 public:
85 VArrayImpl(const int64_t size) : size_(size)
86 {
87 BLI_assert(size_ >= 0);
88 }
89
90 virtual ~VArrayImpl() = default;
91
92 int64_t size() const
93 {
94 return size_;
95 }
96
101 virtual T get(int64_t index) const = 0;
102
104 {
105 return {};
106 }
107
112 virtual void materialize(const IndexMask &mask, T *dst) const
113 {
114 mask.foreach_index([&](const int64_t i) { dst[i] = this->get(i); });
115 }
116
120 virtual void materialize_to_uninitialized(const IndexMask &mask, T *dst) const
121 {
122 mask.foreach_index([&](const int64_t i) { new (dst + i) T(this->get(i)); });
123 }
124
130 virtual void materialize_compressed(const IndexMask &mask, T *dst) const
131 {
132 mask.foreach_index([&](const int64_t i, const int64_t pos) { dst[pos] = this->get(i); });
133 }
134
138 virtual void materialize_compressed_to_uninitialized(const IndexMask &mask, T *dst) const
139 {
140 mask.foreach_index(
141 [&](const int64_t i, const int64_t pos) { new (dst + pos) T(this->get(i)); });
142 }
143
150 virtual bool try_assign_GVArray(GVArray & /*varray*/) const
151 {
152 return false;
153 }
154};
155
157template<typename T> class VMutableArrayImpl : public VArrayImpl<T> {
158 public:
159 using VArrayImpl<T>::VArrayImpl;
160
164 virtual void set(int64_t index, T value) = 0;
165
169 virtual void set_all(Span<T> src)
170 {
171 const CommonVArrayInfo info = this->common_info();
174 src.data(), this->size_, const_cast<T *>(static_cast<const T *>(info.data)));
175 }
176 else {
177 const int64_t size = this->size_;
178 for (int64_t i = 0; i < size; i++) {
179 this->set(i, src[i]);
180 }
181 }
182 }
183
187 virtual bool try_assign_GVMutableArray(GVMutableArray & /*varray*/) const
188 {
189 return false;
190 }
191};
192
197template<typename T> class VArrayImpl_For_Span : public VMutableArrayImpl<T> {
198 protected:
199 T *data_ = nullptr;
200
201 public:
203 : VMutableArrayImpl<T>(data.size()), data_(data.data())
204 {
205 }
206
207 protected:
209
210 T get(const int64_t index) const final
211 {
212 return data_[index];
213 }
214
215 void set(const int64_t index, T value) final
216 {
217 data_[index] = value;
218 }
219
221 {
223 }
224
225 void materialize(const IndexMask &mask, T *dst) const override
226 {
227 mask.foreach_index_optimized<int64_t>([&](const int64_t i) { dst[i] = data_[i]; });
228 }
229
230 void materialize_to_uninitialized(const IndexMask &mask, T *dst) const override
231 {
232 mask.foreach_index_optimized<int64_t>([&](const int64_t i) { new (dst + i) T(data_[i]); });
233 }
234
235 void materialize_compressed(const IndexMask &mask, T *dst) const override
236 {
237 mask.foreach_index_optimized<int64_t>(
238 [&](const int64_t i, const int64_t pos) { dst[pos] = data_[i]; });
239 }
240
241 void materialize_compressed_to_uninitialized(const IndexMask &mask, T *dst) const override
242 {
243 mask.foreach_index_optimized<int64_t>(
244 [&](const int64_t i, const int64_t pos) { new (dst + pos) T(data_[i]); });
245 }
246};
247
252template<typename T> class VArrayImpl_For_Span_final final : public VArrayImpl_For_Span<T> {
253 public:
255
257 /* Cast const away, because the implementation for const and non const spans is shared. */
258 : VArrayImpl_For_Span<T>({const_cast<T *>(data.data()), data.size()})
259 {
260 }
261
262 private:
263 CommonVArrayInfo common_info() const final
264 {
265 return CommonVArrayInfo(CommonVArrayInfo::Type::Span, false, this->data_);
266 }
267};
268
269template<typename T>
271
278template<typename Container, typename T = typename Container::value_type>
280 private:
281 Container container_;
282
283 public:
284 VArrayImpl_For_ArrayContainer(Container container)
285 : VArrayImpl_For_Span<T>(int64_t(container.size())), container_(std::move(container))
286 {
287 this->data_ = const_cast<T *>(container_.data());
288 }
289};
290
296template<typename T> class VArrayImpl_For_Single final : public VArrayImpl<T> {
297 private:
298 T value_;
299
300 public:
301 VArrayImpl_For_Single(T value, const int64_t size)
302 : VArrayImpl<T>(size), value_(std::move(value))
303 {
304 }
305
306 protected:
307 T get(const int64_t /*index*/) const override
308 {
309 return value_;
310 }
311
313 {
315 }
316
317 void materialize(const IndexMask &mask, T *dst) const override
318 {
319 mask.foreach_index([&](const int64_t i) { dst[i] = value_; });
320 }
321
322 void materialize_to_uninitialized(const IndexMask &mask, T *dst) const override
323 {
324 mask.foreach_index([&](const int64_t i) { new (dst + i) T(value_); });
325 }
326
327 void materialize_compressed(const IndexMask &mask, T *dst) const override
328 {
329 initialized_fill_n(dst, mask.size(), value_);
330 }
331
332 void materialize_compressed_to_uninitialized(const IndexMask &mask, T *dst) const override
333 {
334 uninitialized_fill_n(dst, mask.size(), value_);
335 }
336};
337
338template<typename T>
340
345template<typename T, typename GetFunc> class VArrayImpl_For_Func final : public VArrayImpl<T> {
346 private:
347 GetFunc get_func_;
348
349 public:
350 VArrayImpl_For_Func(const int64_t size, GetFunc get_func)
351 : VArrayImpl<T>(size), get_func_(std::move(get_func))
352 {
353 }
354
355 private:
356 T get(const int64_t index) const override
357 {
358 return get_func_(index);
359 }
360
361 void materialize(const IndexMask &mask, T *dst) const override
362 {
363 mask.foreach_index([&](const int64_t i) { dst[i] = get_func_(i); });
364 }
365
366 void materialize_to_uninitialized(const IndexMask &mask, T *dst) const override
367 {
368 mask.foreach_index([&](const int64_t i) { new (dst + i) T(get_func_(i)); });
369 }
370
371 void materialize_compressed(const IndexMask &mask, T *dst) const override
372 {
373 mask.foreach_index([&](const int64_t i, const int64_t pos) { dst[pos] = get_func_(i); });
374 }
375
376 void materialize_compressed_to_uninitialized(const IndexMask &mask, T *dst) const override
377 {
378 mask.foreach_index(
379 [&](const int64_t i, const int64_t pos) { new (dst + pos) T(get_func_(i)); });
380 }
381};
382
386template<typename StructT,
387 typename ElemT,
388 ElemT (*GetFunc)(const StructT &),
389 void (*SetFunc)(StructT &, ElemT) = nullptr>
391 private:
392 StructT *data_;
393
394 public:
396 : VMutableArrayImpl<ElemT>(data.size()), data_(data.data())
397 {
398 }
399
400 template<typename OtherStructT,
401 typename OtherElemT,
402 OtherElemT (*OtherGetFunc)(const OtherStructT &),
403 void (*OtherSetFunc)(OtherStructT &, OtherElemT)>
405
406 private:
407 ElemT get(const int64_t index) const override
408 {
409 return GetFunc(data_[index]);
410 }
411
412 void set(const int64_t index, ElemT value) override
413 {
414 SetFunc(data_[index], std::move(value));
415 }
416
417 void materialize(const IndexMask &mask, ElemT *dst) const override
418 {
419 mask.foreach_index_optimized<int64_t>([&](const int64_t i) { dst[i] = GetFunc(data_[i]); });
420 }
421
422 void materialize_to_uninitialized(const IndexMask &mask, ElemT *dst) const override
423 {
424 mask.foreach_index_optimized<int64_t>(
425 [&](const int64_t i) { new (dst + i) ElemT(GetFunc(data_[i])); });
426 }
427
428 void materialize_compressed(const IndexMask &mask, ElemT *dst) const override
429 {
430 mask.foreach_index_optimized<int64_t>(
431 [&](const int64_t i, const int64_t pos) { dst[pos] = GetFunc(data_[i]); });
432 }
433
434 void materialize_compressed_to_uninitialized(const IndexMask &mask, ElemT *dst) const override
435 {
436 mask.foreach_index_optimized<int64_t>(
437 [&](const int64_t i, const int64_t pos) { new (dst + pos) ElemT(GetFunc(data_[i])); });
438 }
439};
440
441template<typename StructT,
442 typename ElemT,
443 ElemT (*GetFunc)(const StructT &),
444 void (*SetFunc)(StructT &, ElemT)>
445inline constexpr bool
447
448namespace detail {
449
454template<typename T> struct VArrayAnyExtraInfo {
458 const VArrayImpl<T> *(*get_varray)(const void *buffer);
459
460 template<typename StorageT> static constexpr VArrayAnyExtraInfo get()
461 {
462 /* These are the only allowed types in the #Any. */
463 static_assert(
464 std::is_base_of_v<VArrayImpl<T>, StorageT> ||
465 is_same_any_v<StorageT, const VArrayImpl<T> *, std::shared_ptr<const VArrayImpl<T>>>);
466
467 /* Depending on how the virtual array implementation is stored in the #Any, a different
468 * #get_varray function is required. */
469 if constexpr (std::is_base_of_v<VArrayImpl<T>, StorageT>) {
470 return {[](const void *buffer) {
471 return static_cast<const VArrayImpl<T> *>((const StorageT *)buffer);
472 }};
473 }
474 else if constexpr (std::is_same_v<StorageT, const VArrayImpl<T> *>) {
475 return {[](const void *buffer) { return *(const StorageT *)buffer; }};
476 }
477 else if constexpr (std::is_same_v<StorageT, std::shared_ptr<const VArrayImpl<T>>>) {
478 return {[](const void *buffer) { return ((const StorageT *)buffer)->get(); }};
479 }
480 else {
482 return {};
483 }
484 }
485};
486
487} // namespace detail
488
496template<typename T> class VArrayCommon {
497 protected:
506
510 const VArrayImpl<T> *impl_ = nullptr;
519
520 protected:
521 VArrayCommon() = default;
522
525 {
526 impl_ = this->impl_from_storage();
527 }
528
530 VArrayCommon(VArrayCommon &&other) noexcept : storage_(std::move(other.storage_))
531 {
532 impl_ = this->impl_from_storage();
533 other.storage_.reset();
534 other.impl_ = nullptr;
535 }
536
542 {
543 storage_ = impl_;
544 }
545
549 VArrayCommon(std::shared_ptr<const VArrayImpl<T>> impl) : impl_(impl.get())
550 {
551 if (impl) {
552 storage_ = std::move(impl);
553 }
554 }
555
559 template<typename ImplT, typename... Args> void emplace(Args &&...args)
560 {
561 /* Make sure we are actually constructing a #VArrayImpl. */
562 static_assert(std::is_base_of_v<VArrayImpl<T>, ImplT>);
563 if constexpr (std::is_copy_constructible_v<ImplT> && Storage::template is_inline_v<ImplT>) {
564 /* Only inline the implementation when it is copyable and when it fits into the inline
565 * buffer of the storage. */
566 impl_ = &storage_.template emplace<ImplT>(std::forward<Args>(args)...);
567 }
568 else {
569 /* If it can't be inlined, create a new #std::shared_ptr instead and store that in the
570 * storage. */
571 std::shared_ptr<const VArrayImpl<T>> ptr = std::make_shared<ImplT>(
572 std::forward<Args>(args)...);
573 impl_ = &*ptr;
574 storage_ = std::move(ptr);
575 }
576 }
577
579 void copy_from(const VArrayCommon &other)
580 {
581 if (this == &other) {
582 return;
583 }
584 storage_ = other.storage_;
585 impl_ = this->impl_from_storage();
586 }
587
589 void move_from(VArrayCommon &&other) noexcept
590 {
591 if (this == &other) {
592 return;
593 }
594 storage_ = std::move(other.storage_);
595 impl_ = this->impl_from_storage();
596 other.storage_.reset();
597 other.impl_ = nullptr;
598 }
599
603 {
604 if (!storage_.has_value()) {
605 return nullptr;
606 }
607 return storage_.extra_info().get_varray(storage_.get());
608 }
609
610 public:
612 operator bool() const
613 {
614 return impl_ != nullptr;
615 }
616
622 T operator[](const int64_t index) const
623 {
624 BLI_assert(*this);
625 BLI_assert(index >= 0);
626 BLI_assert(index < this->size());
627 return impl_->get(index);
628 }
629
634 T get(const int64_t index) const
635 {
636 return (*this)[index];
637 }
638
643 int64_t size() const
644 {
645 if (impl_ == nullptr) {
646 return 0;
647 }
648 return impl_->size();
649 }
653 T first() const
654 {
655 return (*this)[0];
656 }
660 T last(const int64_t n = 0) const
661 {
662 return (*this)[this->size() - 1 - n];
663 }
664
666 bool is_empty() const
667 {
668 return this->size() == 0;
669 }
670
672 {
673 return IndexRange(this->size());
674 }
675
677 {
678 BLI_assert(*this);
679 return impl_->common_info();
680 }
681
683 bool is_span() const
684 {
685 BLI_assert(*this);
686 const CommonVArrayInfo info = impl_->common_info();
687 return info.type == CommonVArrayInfo::Type::Span;
688 }
689
695 {
696 BLI_assert(this->is_span());
697 const CommonVArrayInfo info = impl_->common_info();
698 return Span<T>(static_cast<const T *>(info.data), this->size());
699 }
700
702 bool is_single() const
703 {
704 BLI_assert(*this);
705 const CommonVArrayInfo info = impl_->common_info();
707 }
708
714 {
715 BLI_assert(this->is_single());
716 const CommonVArrayInfo info = impl_->common_info();
717 return *static_cast<const T *>(info.data);
718 }
719
723 std::optional<T> get_if_single() const
724 {
725 const CommonVArrayInfo info = impl_->common_info();
727 return std::nullopt;
728 }
729 return *static_cast<const T *>(info.data);
730 }
731
733 void materialize(MutableSpan<T> r_span) const
734 {
735 this->materialize(IndexMask(this->size()), r_span);
736 }
737
739 void materialize(const IndexMask &mask, MutableSpan<T> r_span) const
740 {
741 BLI_assert(mask.min_array_size() <= this->size());
742 impl_->materialize(mask, r_span.data());
743 }
744
746 {
747 this->materialize_to_uninitialized(IndexMask(this->size()), r_span);
748 }
749
751 {
752 BLI_assert(mask.min_array_size() <= this->size());
753 impl_->materialize_to_uninitialized(mask, r_span.data());
754 }
755
757 void materialize_compressed(const IndexMask &mask, MutableSpan<T> r_span) const
758 {
759 impl_->materialize_compressed(mask, r_span.data());
760 }
761
763 {
764 impl_->materialize_compressed_to_uninitialized(mask, r_span.data());
765 }
766
768 bool try_assign_GVArray(GVArray &varray) const
769 {
770 return impl_->try_assign_GVArray(varray);
771 }
772
774 {
775 return impl_;
776 }
777};
778
779template<typename T> class VMutableArray;
780
788namespace varray_tag {
789struct span {};
790struct single_ref {};
791struct single {};
792} // namespace varray_tag
793
799template<typename T> class VArray : public VArrayCommon<T> {
800 friend VMutableArray<T>;
801
802 public:
803 VArray() = default;
804 VArray(const VArray &other) = default;
805 VArray(VArray &&other) noexcept = default;
806
808
809 VArray(std::shared_ptr<const VArrayImpl<T>> impl) : VArrayCommon<T>(std::move(impl)) {}
810
812 {
813 this->template emplace<VArrayImpl_For_Span_final<T>>(span);
814 }
815
816 VArray(varray_tag::single /*tag*/, T value, const int64_t size)
817 {
818 this->template emplace<VArrayImpl_For_Single<T>>(std::move(value), size);
819 }
820
824 template<typename ImplT, typename... Args> static VArray For(Args &&...args)
825 {
826 static_assert(std::is_base_of_v<VArrayImpl<T>, ImplT>);
827 VArray varray;
828 varray.template emplace<ImplT>(std::forward<Args>(args)...);
829 return varray;
830 }
831
835 static VArray ForSingle(T value, const int64_t size)
836 {
837 return VArray(varray_tag::single{}, std::move(value), size);
838 }
839
844 static VArray ForSpan(Span<T> values)
845 {
846 return VArray(varray_tag::span{}, values);
847 }
848
853 template<typename GetFunc> static VArray ForFunc(const int64_t size, GetFunc get_func)
854 {
855 return VArray::For<VArrayImpl_For_Func<T, decltype(get_func)>>(size, std::move(get_func));
856 }
857
862 template<typename StructT, T (*GetFunc)(const StructT &)>
864 {
865 /* Cast const away, because the virtual array implementation for const and non const derived
866 * spans is shared. */
867 MutableSpan<StructT> span{const_cast<StructT *>(values.data()), values.size()};
869 }
870
876 template<typename ContainerT> static VArray ForContainer(ContainerT container)
877 {
878 return VArray::For<VArrayImpl_For_ArrayContainer<ContainerT>>(std::move(container));
879 }
880
881 VArray &operator=(const VArray &other)
882 {
883 this->copy_from(other);
884 return *this;
885 }
886
887 VArray &operator=(VArray &&other) noexcept
888 {
889 this->move_from(std::move(other));
890 return *this;
891 }
892};
893
897template<typename T> class VMutableArray : public VArrayCommon<T> {
898 public:
899 VMutableArray() = default;
900 VMutableArray(const VMutableArray &other) = default;
901 VMutableArray(VMutableArray &&other) noexcept = default;
902
904
906 : VArrayCommon<T>(std::move(impl))
907 {
908 }
909
913 template<typename ImplT, typename... Args> static VMutableArray For(Args &&...args)
914 {
915 static_assert(std::is_base_of_v<VMutableArrayImpl<T>, ImplT>);
916 VMutableArray varray;
917 varray.template emplace<ImplT>(std::forward<Args>(args)...);
918 return varray;
919 }
920
928
933 template<typename StructT, T (*GetFunc)(const StructT &), void (*SetFunc)(StructT &, T)>
938
940 operator VArray<T>() const &
941 {
942 VArray<T> varray;
943 varray.copy_from(*this);
944 return varray;
945 }
946
948 operator VArray<T>() && noexcept
949 {
950 VArray<T> varray;
951 varray.move_from(std::move(*this));
952 return varray;
953 }
954
956 {
957 this->copy_from(other);
958 return *this;
959 }
960
962 {
963 this->move_from(std::move(other));
964 return *this;
965 }
966
972 {
973 BLI_assert(this->is_span());
974 const CommonVArrayInfo info = this->get_impl()->common_info();
975 return MutableSpan<T>(const_cast<T *>(static_cast<const T *>(info.data)), this->size());
976 }
977
981 void set(const int64_t index, T value)
982 {
983 BLI_assert(index >= 0);
984 BLI_assert(index < this->size());
985 this->get_impl()->set(index, std::move(value));
986 }
987
991 void set_all(Span<T> src)
992 {
993 BLI_assert(src.size() == this->size());
994 this->get_impl()->set_all(src);
995 }
996
999 {
1000 return this->get_impl()->try_assign_GVMutableArray(varray);
1001 }
1002
1003 private:
1005 VMutableArrayImpl<T> *get_impl() const
1006 {
1007 /* This cast is valid by the invariant that a #VMutableArray->impl_ is always a
1008 * #VMutableArrayImpl. */
1009 return (VMutableArrayImpl<T> *)this->impl_;
1010 }
1011};
1012
1013template<typename T> static constexpr bool is_VArray_v = false;
1014template<typename T> static constexpr bool is_VArray_v<VArray<T>> = true;
1015
1016template<typename T> static constexpr bool is_VMutableArray_v = false;
1017template<typename T> static constexpr bool is_VMutableArray_v<VMutableArray<T>> = true;
1018
1030template<typename T> class VArraySpan final : public Span<T> {
1031 private:
1032 VArray<T> varray_;
1033 Array<T> owned_data_;
1034
1035 public:
1036 VArraySpan() = default;
1037
1038 VArraySpan(const VArray<T> &varray) : VArraySpan(VArray<T>(varray)) {}
1039
1040 VArraySpan(VArray<T> &&varray) : Span<T>(), varray_(std::move(varray))
1041 {
1042 if (!varray_) {
1043 return;
1044 }
1045 this->size_ = varray_.size();
1046 const CommonVArrayInfo info = varray_.common_info();
1047 if (info.type == CommonVArrayInfo::Type::Span) {
1048 this->data_ = static_cast<const T *>(info.data);
1049 }
1050 else {
1051 owned_data_.~Array();
1052 new (&owned_data_) Array<T>(varray_.size(), NoInitialization{});
1053 varray_.materialize_to_uninitialized(owned_data_);
1054 this->data_ = owned_data_.data();
1055 }
1056 }
1057
1059 : varray_(std::move(other.varray_)), owned_data_(std::move(other.owned_data_))
1060 {
1061 if (!varray_) {
1062 return;
1063 }
1064 this->size_ = varray_.size();
1065 const CommonVArrayInfo info = varray_.common_info();
1066 if (info.type == CommonVArrayInfo::Type::Span) {
1067 this->data_ = static_cast<const T *>(info.data);
1068 }
1069 else {
1070 this->data_ = owned_data_.data();
1071 }
1072 other.data_ = nullptr;
1073 other.size_ = 0;
1074 }
1075
1077 {
1078 if (this == &other) {
1079 return *this;
1080 }
1081 std::destroy_at(this);
1082 new (this) VArraySpan(std::move(other));
1083 return *this;
1084 }
1085};
1086
1087namespace internal {
1089}
1090
1098template<typename T> class MutableVArraySpan final : public MutableSpan<T> {
1099 private:
1100 VMutableArray<T> varray_;
1101 Array<T> owned_data_;
1102 bool save_has_been_called_ = false;
1103 bool show_not_saved_warning_ = true;
1104
1105 public:
1107
1108 /* Create a span for any virtual array. This is cheap when the virtual array is a span itself. If
1109 * not, a new array has to be allocated as a wrapper for the underlying virtual array. */
1110 MutableVArraySpan(VMutableArray<T> varray, const bool copy_values_to_span = true)
1111 : MutableSpan<T>(), varray_(std::move(varray))
1112 {
1113 if (!varray_) {
1114 return;
1115 }
1116
1117 this->size_ = varray_.size();
1118 const CommonVArrayInfo info = varray_.common_info();
1119 if (info.type == CommonVArrayInfo::Type::Span) {
1120 this->data_ = const_cast<T *>(static_cast<const T *>(info.data));
1121 }
1122 else {
1123 if (copy_values_to_span) {
1124 owned_data_.~Array();
1125 new (&owned_data_) Array<T>(varray_.size(), NoInitialization{});
1126 varray_.materialize_to_uninitialized(owned_data_);
1127 }
1128 else {
1129 owned_data_.reinitialize(varray_.size());
1130 }
1131 this->data_ = owned_data_.data();
1132 }
1133 }
1134
1136 : varray_(std::move(other.varray_)),
1137 owned_data_(std::move(other.owned_data_)),
1138 show_not_saved_warning_(other.show_not_saved_warning_)
1139 {
1140 if (!varray_) {
1141 return;
1142 }
1143
1144 this->size_ = varray_.size();
1145 const CommonVArrayInfo info = varray_.common_info();
1146 if (info.type == CommonVArrayInfo::Type::Span) {
1147 this->data_ = static_cast<T *>(const_cast<void *>(info.data));
1148 }
1149 else {
1150 this->data_ = owned_data_.data();
1151 }
1152 other.data_ = nullptr;
1153 other.size_ = 0;
1154 }
1155
1157 {
1158 if (varray_) {
1159 if (show_not_saved_warning_) {
1160 if (!save_has_been_called_) {
1162 }
1163 }
1164 }
1165 }
1166
1168 {
1169 if (this == &other) {
1170 return *this;
1171 }
1172 std::destroy_at(this);
1173 new (this) MutableVArraySpan(std::move(other));
1174 return *this;
1175 }
1176
1178 {
1179 return varray_;
1180 }
1181
1182 /* Write back all values from a temporary allocated array to the underlying virtual array. */
1183 void save()
1184 {
1185 save_has_been_called_ = true;
1186 if (this->data_ != owned_data_.data()) {
1187 return;
1188 }
1189 varray_.set_all(owned_data_);
1190 }
1191
1193 {
1194 show_not_saved_warning_ = false;
1195 }
1196};
1197
1198template<typename T> class SingleAsSpan {
1199 private:
1200 T value_;
1201 int64_t size_;
1202
1203 public:
1204 SingleAsSpan(T value, int64_t size) : value_(std::move(value)), size_(size)
1205 {
1206 BLI_assert(size_ >= 0);
1207 }
1208
1209 SingleAsSpan(const VArray<T> &varray) : SingleAsSpan(varray.get_internal_single(), varray.size())
1210 {
1211 }
1212
1213 const T &operator[](const int64_t index) const
1214 {
1215 BLI_assert(index >= 0);
1216 BLI_assert(index < size_);
1217 UNUSED_VARS_NDEBUG(index);
1218 return value_;
1219 }
1220};
1221
1222template<typename T> class VArrayRef {
1223 private:
1224 const VArray<T> &ref_;
1225
1226 public:
1227 VArrayRef(const VArray<T> &ref) : ref_(ref) {}
1228
1229 const T operator[](const int64_t index) const
1230 {
1231 return ref_[index];
1232 }
1233};
1234
1236template<typename T, bool UseSingle, bool UseSpan> struct VArrayDevirtualizer {
1238
1239 template<typename Fn> bool devirtualize(const Fn &fn) const
1240 {
1241 const CommonVArrayInfo info = this->varray.common_info();
1242 const int64_t size = this->varray.size();
1243 if constexpr (UseSingle) {
1245 return fn(SingleAsSpan<T>(*static_cast<const T *>(info.data), size));
1246 }
1247 }
1248 if constexpr (UseSpan) {
1249 if (info.type == CommonVArrayInfo::Type::Span) {
1250 return fn(Span<T>(static_cast<const T *>(info.data), size));
1251 }
1252 }
1253 return false;
1254 }
1255};
1256
1265template<typename T, typename Func>
1266inline void devirtualize_varray(const VArray<T> &varray, const Func &func, bool enable = true)
1267{
1268 if (enable) {
1270 std::make_tuple(VArrayDevirtualizer<T, true, true>{varray}), func))
1271 {
1272 return;
1273 }
1274 }
1275 func(VArrayRef<T>(varray));
1276}
1277
1283template<typename T1, typename T2, typename Func>
1284inline void devirtualize_varray2(const VArray<T1> &varray1,
1285 const VArray<T2> &varray2,
1286 const Func &func,
1287 bool enable = true)
1288{
1289 if (enable) {
1291 std::make_tuple(VArrayDevirtualizer<T1, true, true>{varray1},
1293 func))
1294 {
1295 return;
1296 }
1297 }
1298 func(VArrayRef<T1>(varray1), VArrayRef<T2>(varray2));
1299}
1300
1301} // namespace blender
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
#define UNUSED_VARS_NDEBUG(...)
const RealExtraInfo & extra_info() const
Definition BLI_any.hh:375
bool has_value() const
Definition BLI_any.hh:255
void * get()
Definition BLI_any.hh:324
const T * data() const
Definition BLI_array.hh:301
void reinitialize(const int64_t new_size)
Definition BLI_array.hh:388
constexpr int64_t size() const
Definition BLI_span.hh:494
constexpr T * data() const
Definition BLI_span.hh:540
const VMutableArray< T > & varray() const
MutableVArraySpan & operator=(MutableVArraySpan &&other)
MutableVArraySpan(MutableVArraySpan &&other)
MutableVArraySpan(VMutableArray< T > varray, const bool copy_values_to_span=true)
SingleAsSpan(const VArray< T > &varray)
const T & operator[](const int64_t index) const
SingleAsSpan(T value, int64_t size)
constexpr const T * data() const
Definition BLI_span.hh:216
int64_t size_
Definition BLI_span.hh:87
constexpr int64_t size() const
Definition BLI_span.hh:253
std::optional< T > get_if_single() const
IndexRange index_range() const
VArrayCommon(std::shared_ptr< const VArrayImpl< T > > impl)
void materialize(MutableSpan< T > r_span) const
T operator[](const int64_t index) const
T last(const int64_t n=0) const
VArrayCommon(const VArrayImpl< T > *impl)
void copy_from(const VArrayCommon &other)
void materialize_compressed_to_uninitialized(const IndexMask &mask, MutableSpan< T > r_span) const
VArrayCommon(const VArrayCommon &other)
const VArrayImpl< T > * impl_from_storage() const
const VArrayImpl< T > * impl_
void materialize(const IndexMask &mask, MutableSpan< T > r_span) const
VArrayCommon(VArrayCommon &&other) noexcept
void move_from(VArrayCommon &&other) noexcept
T get(const int64_t index) const
void materialize_to_uninitialized(const IndexMask &mask, MutableSpan< T > r_span) const
const VArrayImpl< T > * get_implementation() const
bool try_assign_GVArray(GVArray &varray) const
void materialize_to_uninitialized(MutableSpan< T > r_span) const
void materialize_compressed(const IndexMask &mask, MutableSpan< T > r_span) const
CommonVArrayInfo common_info() const
Span< T > get_internal_span() const
void emplace(Args &&...args)
VArrayImpl_For_DerivedSpan(const MutableSpan< StructT > data)
VArrayImpl_For_Func(const int64_t size, GetFunc get_func)
void materialize_compressed(const IndexMask &mask, T *dst) const override
VArrayImpl_For_Single(T value, const int64_t size)
void materialize_to_uninitialized(const IndexMask &mask, T *dst) const override
CommonVArrayInfo common_info() const override
T get(const int64_t) const override
void materialize(const IndexMask &mask, T *dst) const override
void materialize_compressed_to_uninitialized(const IndexMask &mask, T *dst) const override
VArrayImpl_For_Span_final(const Span< T > data)
CommonVArrayInfo common_info() const override
void set(const int64_t index, T value) final
VArrayImpl_For_Span(const int64_t size)
void materialize_compressed(const IndexMask &mask, T *dst) const override
void materialize_compressed_to_uninitialized(const IndexMask &mask, T *dst) const override
void materialize(const IndexMask &mask, T *dst) const override
T get(const int64_t index) const final
void materialize_to_uninitialized(const IndexMask &mask, T *dst) const override
VArrayImpl_For_Span(const MutableSpan< T > data)
virtual void materialize_compressed(const IndexMask &mask, T *dst) const
virtual bool try_assign_GVArray(GVArray &) const
virtual void materialize_compressed_to_uninitialized(const IndexMask &mask, T *dst) const
virtual void materialize_to_uninitialized(const IndexMask &mask, T *dst) const
virtual CommonVArrayInfo common_info() const
virtual void materialize(const IndexMask &mask, T *dst) const
virtual T get(int64_t index) const =0
VArrayImpl(const int64_t size)
virtual ~VArrayImpl()=default
VArrayRef(const VArray< T > &ref)
const T operator[](const int64_t index) const
VArraySpan(VArray< T > &&varray)
VArraySpan(VArraySpan &&other)
VArraySpan(const VArray< T > &varray)
VArraySpan & operator=(VArraySpan &&other)
VArray(const VArrayImpl< T > *impl)
VArray(const VArray &other)=default
VArray(varray_tag::single, T value, const int64_t size)
static VArray ForDerivedSpan(Span< StructT > values)
VArray(VArray &&other) noexcept=default
VArray & operator=(const VArray &other)
static VArray ForContainer(ContainerT container)
VArray(varray_tag::span, Span< T > span)
VArray(std::shared_ptr< const VArrayImpl< T > > impl)
static VArray ForSingle(T value, const int64_t size)
static VArray For(Args &&...args)
static VArray ForSpan(Span< T > values)
VArray & operator=(VArray &&other) noexcept
static VArray ForFunc(const int64_t size, GetFunc get_func)
VArray()=default
virtual void set(int64_t index, T value)=0
virtual bool try_assign_GVMutableArray(GVMutableArray &) const
virtual void set_all(Span< T > src)
void set(const int64_t index, T value)
VMutableArray(std::shared_ptr< const VMutableArrayImpl< T > > impl)
static VMutableArray ForDerivedSpan(MutableSpan< StructT > values)
VMutableArray & operator=(const VMutableArray &other)
static VMutableArray ForSpan(MutableSpan< T > values)
static VMutableArray For(Args &&...args)
bool try_assign_GVMutableArray(GVMutableArray &varray) const
VMutableArray & operator=(VMutableArray &&other) noexcept
VMutableArray(VMutableArray &&other) noexcept=default
VMutableArray(const VMutableArray &other)=default
MutableSpan< T > get_internal_span() const
VMutableArray(const VMutableArrayImpl< T > *impl)
void set_all(Span< T > src)
node_ attributes set("label", ss.str())
#define T
void print_mutable_varray_span_warning()
constexpr bool is_same_any_v
void devirtualize_varray(const VArray< T > &varray, const Func &func, bool enable=true)
void devirtualize_varray2(const VArray< T1 > &varray1, const VArray< T2 > &varray2, const Func &func, bool enable=true)
static constexpr bool is_VArray_v
void initialized_fill_n(T *dst, int64_t n, const T &value)
bool call_with_devirtualized_parameters(const std::tuple< Devirtualizers... > &devis, const Fn &fn)
static constexpr bool is_VMutableArray_v
void uninitialized_fill_n(T *dst, int64_t n, const T &value)
void initialized_copy_n(const T *src, int64_t n, T *dst)
constexpr bool is_trivial_extended_v
static IOCIOImpl * impl
Definition ocio_capi.cc:9
__int64 int64_t
Definition stdint.h:89
unsigned char uint8_t
Definition stdint.h:78
CommonVArrayInfo(const Type _type, const bool _may_have_ownership, const void *_data)
bool devirtualize(const Fn &fn) const
static constexpr VArrayAnyExtraInfo get()
PointerRNA * ptr
Definition wm_files.cc:4126