| 
									
										
										
										
											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. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \file
 | 
					
						
							|  |  |  |  * \ingroup fn | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |  * A`GVectorArray` is a container for a fixed amount of dynamically growing vectors with a generic | 
					
						
							|  |  |  |  * data type. Its main use case is to store many small vectors with few separate allocations. Using | 
					
						
							|  |  |  |  * this structure is generally more efficient than allocating each vector separately. | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BLI_array.hh"
 | 
					
						
							|  |  |  | #include "BLI_linear_allocator.hh"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  | #include "FN_generic_virtual_vector_array.hh"
 | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  | namespace blender::fn { | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  | /* An array of vectors containing elements of a generic type. */ | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  | class GVectorArray : NonCopyable, NonMovable { | 
					
						
							|  |  |  |  private: | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |   struct Item { | 
					
						
							|  |  |  |     void *start = nullptr; | 
					
						
							|  |  |  |     int64_t length = 0; | 
					
						
							|  |  |  |     int64_t capacity = 0; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Use a linear allocator to pack many small vectors together. Currently, memory from reallocated
 | 
					
						
							|  |  |  |    * vectors is not reused. This can be improved in the future. */ | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |   LinearAllocator<> allocator_; | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |   /* The data type of individual elements. */ | 
					
						
							|  |  |  |   const CPPType &type_; | 
					
						
							|  |  |  |   /* The size of an individual element. This is inlined from `type_.size()` for easier access. */ | 
					
						
							|  |  |  |   const int64_t element_size_; | 
					
						
							|  |  |  |   /* The individual vectors. */ | 
					
						
							|  |  |  |   Array<Item> items_; | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |  public: | 
					
						
							|  |  |  |   GVectorArray() = delete; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |   GVectorArray(const CPPType &type, int64_t array_size); | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |   ~GVectorArray(); | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |   int64_t size() const | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |     return items_.size(); | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   bool is_empty() const | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |     return items_.is_empty(); | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const CPPType &type() const | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |     return type_; | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |   void append(int64_t index, const void *value); | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |   /* Add multiple elements to a single vector. */ | 
					
						
							|  |  |  |   void extend(int64_t index, const GVArray &values); | 
					
						
							|  |  |  |   void extend(int64_t index, GSpan values); | 
					
						
							| 
									
										
										
										
											2020-06-22 15:48:08 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |   /* Add multiple elements to multiple vectors. */ | 
					
						
							|  |  |  |   void extend(IndexMask mask, const GVVectorArray &values); | 
					
						
							|  |  |  |   void extend(IndexMask mask, const GVectorArray &values); | 
					
						
							| 
									
										
										
										
											2020-06-22 15:48:08 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |   GMutableSpan operator[](int64_t index); | 
					
						
							|  |  |  |   GSpan operator[](int64_t index) const; | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |  private: | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |   void realloc_to_at_least(Item &item, int64_t min_capacity); | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  | /* A non-owning typed mutable reference to an `GVectorArray`. It simplifies access when the type of
 | 
					
						
							|  |  |  |  * the data is known at compile time. */ | 
					
						
							|  |  |  | template<typename T> class GVectorArray_TypedMutableRef { | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |  private: | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |   GVectorArray *vector_array_; | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |  public: | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |   GVectorArray_TypedMutableRef(GVectorArray &vector_array) : vector_array_(&vector_array) | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |     BLI_assert(vector_array_->type().is<T>()); | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |   int64_t size() const | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     return vector_array_->size(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   bool is_empty() const | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     return vector_array_->is_empty(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void append(const int64_t index, const T &value) | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |     vector_array_->append(index, &value); | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |   void extend(const int64_t index, const Span<T> values) | 
					
						
							| 
									
										
										
										
											2020-06-22 15:48:08 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |     vector_array_->extend(index, values); | 
					
						
							| 
									
										
										
										
											2020-06-22 15:48:08 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |   void extend(const int64_t index, const VArray<T> &values) | 
					
						
							| 
									
										
										
										
											2020-06-22 15:48:08 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2021-04-17 15:13:20 +02:00
										 |  |  |     GVArray_For_VArray<T> array{values}; | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |     this->extend(index, array); | 
					
						
							| 
									
										
										
										
											2020-06-22 15:48:08 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |   MutableSpan<T> operator[](const int64_t index) | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |     return (*vector_array_)[index].typed<T>(); | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  | /* A generic virtual vector array implementation for a `GVectorArray`. */ | 
					
						
							| 
									
										
										
										
											2021-04-17 15:13:20 +02:00
										 |  |  | class GVVectorArray_For_GVectorArray : public GVVectorArray { | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |  private: | 
					
						
							|  |  |  |   const GVectorArray &vector_array_; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  public: | 
					
						
							| 
									
										
										
										
											2021-04-17 15:13:20 +02:00
										 |  |  |   GVVectorArray_For_GVectorArray(const GVectorArray &vector_array) | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |       : GVVectorArray(vector_array.type(), vector_array.size()), vector_array_(vector_array) | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |  protected: | 
					
						
							|  |  |  |   int64_t get_vector_size_impl(const int64_t index) const override | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |     return vector_array_[index].size(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void get_vector_element_impl(const int64_t index, | 
					
						
							|  |  |  |                                const int64_t index_in_vector, | 
					
						
							|  |  |  |                                void *r_value) const override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     type_->copy_to_initialized(vector_array_[index][index_in_vector], r_value); | 
					
						
							| 
									
										
										
										
											2020-06-16 16:35:57 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 14:25:20 +02:00
										 |  |  | }  // namespace blender::fn
 |