| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  |  * of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-07 09:50:34 +02:00
										 |  |  | #pragma once
 | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** \file
 | 
					
						
							|  |  |  |  * \ingroup fn | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * An ArraySpan is a span where every element contains an array (instead of a single element as is | 
					
						
							| 
									
										
										
										
											2020-10-19 08:12:33 -07:00
										 |  |  |  * the case in a normal span). Its main use case is to reference many small arrays. | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "FN_spans.hh"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 14:25:20 +02:00
										 |  |  | namespace blender::fn { | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2020-06-22 15:48:08 +02:00
										 |  |  |  * Depending on the use case, the referenced data might have a different structure. More | 
					
						
							|  |  |  |  * categories can be added when necessary. | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-06-22 15:48:08 +02:00
										 |  |  | enum class VArraySpanCategory { | 
					
						
							|  |  |  |   SingleArray, | 
					
						
							|  |  |  |   StartsAndSizes, | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-22 15:48:08 +02:00
										 |  |  | template<typename T> class VArraySpanBase { | 
					
						
							|  |  |  |  protected: | 
					
						
							| 
									
										
										
										
											2020-07-20 12:16:20 +02:00
										 |  |  |   int64_t virtual_size_; | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |   VArraySpanCategory category_; | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   union { | 
					
						
							|  |  |  |     struct { | 
					
						
							|  |  |  |       const T *start; | 
					
						
							| 
									
										
										
										
											2020-07-20 12:16:20 +02:00
										 |  |  |       int64_t size; | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |     } single_array; | 
					
						
							|  |  |  |     struct { | 
					
						
							|  |  |  |       const T *const *starts; | 
					
						
							| 
									
										
										
										
											2020-07-20 12:16:20 +02:00
										 |  |  |       const int64_t *sizes; | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |     } starts_and_sizes; | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |   } data_; | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |  public: | 
					
						
							| 
									
										
										
										
											2020-06-22 15:48:08 +02:00
										 |  |  |   bool is_single_array() const | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |     switch (category_) { | 
					
						
							| 
									
										
										
										
											2020-06-22 15:48:08 +02:00
										 |  |  |       case VArraySpanCategory::SingleArray: | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |       case VArraySpanCategory::StartsAndSizes: | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |         return virtual_size_ == 1; | 
					
						
							| 
									
										
										
										
											2020-06-22 15:48:08 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     BLI_assert(false); | 
					
						
							|  |  |  |     return false; | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-22 15:48:08 +02:00
										 |  |  |   bool is_empty() const | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |     return this->virtual_size_ == 0; | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 12:16:20 +02:00
										 |  |  |   int64_t size() const | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |     return this->virtual_size_; | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-06-22 15:48:08 +02:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-22 15:48:08 +02:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * 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) | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2020-06-22 15:48:08 +02:00
										 |  |  |     memcpy(this, &other, sizeof(VArraySpanBase<void>)); | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-22 15:48:08 +02:00
										 |  |  |  public: | 
					
						
							|  |  |  |   VArraySpan() | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |     this->virtual_size_ = 0; | 
					
						
							|  |  |  |     this->category_ = VArraySpanCategory::StartsAndSizes; | 
					
						
							|  |  |  |     this->data_.starts_and_sizes.starts = nullptr; | 
					
						
							|  |  |  |     this->data_.starts_and_sizes.sizes = nullptr; | 
					
						
							| 
									
										
										
										
											2020-06-22 15:48:08 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 12:16:20 +02:00
										 |  |  |   VArraySpan(Span<T> span, int64_t virtual_size) | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2020-07-20 12:16:20 +02:00
										 |  |  |     BLI_assert(virtual_size >= 0); | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |     this->virtual_size_ = virtual_size; | 
					
						
							|  |  |  |     this->category_ = VArraySpanCategory::SingleArray; | 
					
						
							|  |  |  |     this->data_.single_array.start = span.data(); | 
					
						
							|  |  |  |     this->data_.single_array.size = span.size(); | 
					
						
							| 
									
										
										
										
											2020-06-22 15:48:08 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 12:16:20 +02:00
										 |  |  |   VArraySpan(Span<const T *> starts, Span<int64_t> sizes) | 
					
						
							| 
									
										
										
										
											2020-06-22 15:48:08 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |     BLI_assert(starts.size() == sizes.size()); | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |     this->virtual_size_ = starts.size(); | 
					
						
							|  |  |  |     this->category_ = VArraySpanCategory::StartsAndSizes; | 
					
						
							|  |  |  |     this->data_.starts_and_sizes.starts = starts.begin(); | 
					
						
							|  |  |  |     this->data_.starts_and_sizes.sizes = sizes.begin(); | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 12:16:20 +02:00
										 |  |  |   VSpan<T> operator[](int64_t index) const | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2020-07-20 12:16:20 +02:00
										 |  |  |     BLI_assert(index >= 0); | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |     BLI_assert(index < this->virtual_size_); | 
					
						
							|  |  |  |     switch (this->category_) { | 
					
						
							| 
									
										
										
										
											2020-06-22 15:48:08 +02:00
										 |  |  |       case VArraySpanCategory::SingleArray: | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |         return VSpan<T>(Span<T>(this->data_.single_array.start, this->data_.single_array.size)); | 
					
						
							| 
									
										
										
										
											2020-06-22 15:48:08 +02:00
										 |  |  |       case VArraySpanCategory::StartsAndSizes: | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |         return VSpan<T>(Span<T>(this->data_.starts_and_sizes.starts[index], | 
					
						
							|  |  |  |                                 this->data_.starts_and_sizes.sizes[index])); | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     BLI_assert(false); | 
					
						
							|  |  |  |     return {}; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * A generic virtual array span. It's just like a VArraySpan, but the type is only known at | 
					
						
							|  |  |  |  * run-time. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-06-22 15:48:08 +02:00
										 |  |  | class GVArraySpan : public VArraySpanBase<void> { | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |  private: | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |   const CPPType *type_; | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   GVArraySpan() = default; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  public: | 
					
						
							|  |  |  |   GVArraySpan(const CPPType &type) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |     this->type_ = &type; | 
					
						
							|  |  |  |     this->virtual_size_ = 0; | 
					
						
							|  |  |  |     this->category_ = VArraySpanCategory::StartsAndSizes; | 
					
						
							|  |  |  |     this->data_.starts_and_sizes.starts = nullptr; | 
					
						
							|  |  |  |     this->data_.starts_and_sizes.sizes = nullptr; | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 12:16:20 +02:00
										 |  |  |   GVArraySpan(GSpan array, int64_t virtual_size) | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |     this->type_ = &array.type(); | 
					
						
							|  |  |  |     this->virtual_size_ = virtual_size; | 
					
						
							|  |  |  |     this->category_ = VArraySpanCategory::SingleArray; | 
					
						
							| 
									
										
										
										
											2020-07-23 18:07:31 +02:00
										 |  |  |     this->data_.single_array.start = array.data(); | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |     this->data_.single_array.size = array.size(); | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 12:16:20 +02:00
										 |  |  |   GVArraySpan(const CPPType &type, Span<const void *> starts, Span<int64_t> sizes) | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |     BLI_assert(starts.size() == sizes.size()); | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |     this->type_ = &type; | 
					
						
							|  |  |  |     this->virtual_size_ = starts.size(); | 
					
						
							|  |  |  |     this->category_ = VArraySpanCategory::StartsAndSizes; | 
					
						
							|  |  |  |     this->data_.starts_and_sizes.starts = (void **)starts.begin(); | 
					
						
							|  |  |  |     this->data_.starts_and_sizes.sizes = sizes.begin(); | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-22 15:48:08 +02:00
										 |  |  |   template<typename T> GVArraySpan(VArraySpan<T> other) | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |     this->type_ = &CPPType::get<T>(); | 
					
						
							| 
									
										
										
										
											2020-06-22 15:48:08 +02:00
										 |  |  |     memcpy(this, &other, sizeof(VArraySpanBase<void>)); | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const CPPType &type() const | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |     return *this->type_; | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   template<typename T> VArraySpan<T> typed() const | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |     BLI_assert(type_->is<T>()); | 
					
						
							| 
									
										
										
										
											2020-06-22 15:48:08 +02:00
										 |  |  |     return VArraySpan<T>(*this); | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 12:16:20 +02:00
										 |  |  |   GVSpan operator[](int64_t index) const | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |     BLI_assert(index < virtual_size_); | 
					
						
							|  |  |  |     switch (category_) { | 
					
						
							| 
									
										
										
										
											2020-06-22 15:48:08 +02:00
										 |  |  |       case VArraySpanCategory::SingleArray: | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |         return GVSpan(GSpan(*type_, data_.single_array.start, data_.single_array.size)); | 
					
						
							| 
									
										
										
										
											2020-06-22 15:48:08 +02:00
										 |  |  |       case VArraySpanCategory::StartsAndSizes: | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |         return GVSpan(GSpan( | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |             *type_, data_.starts_and_sizes.starts[index], data_.starts_and_sizes.sizes[index])); | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     BLI_assert(false); | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |     return GVSpan(*type_); | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 14:25:20 +02:00
										 |  |  | }  // namespace blender::fn
 |