Get the latest Blender, older versions, or experimental builds.
Stay up-to-date with the new features in the latest Blender releases.
Access production assets and knowledge from the open movies.
Documentation on the usage and features in Blender.
Latest development updates, by Blender developers.
Guidelines, release notes and development docs.
A platform to collect and share results of the Blender Benchmark.
The yearly event that brings the community together.
Support core development with a monthly contribution.
Perform a single donation with more payment options available.
Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.
/* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bli
*
* 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.
*/
#include "BLI_array.hh"
#include "BLI_generic_virtual_vector_array.hh"
#include "BLI_linear_allocator.hh"
namespace blender {
/* An array of vectors containing elements of a generic type. */
class GVectorArray : NonCopyable, NonMovable {
private:
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. */
LinearAllocator<> allocator_;
/* 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_;
public:
GVectorArray() = delete;
GVectorArray(const CPPType &type, int64_t array_size);
~GVectorArray();
int64_t size() const
{
return items_.size();
}
bool is_empty() const
return items_.is_empty();
const CPPType &type() const
return type_;
void append(int64_t index, const void *value);
/* Add multiple elements to a single vector. */
void extend(int64_t index, const GVArray &values);
void extend(int64_t index, GSpan values);
/* Add multiple elements to multiple vectors. */
void extend(IndexMask mask, const GVVectorArray &values);
void extend(IndexMask mask, const GVectorArray &values);
void clear(IndexMask mask);
GMutableSpan operator[](int64_t index);
GSpan operator[](int64_t index) const;
void realloc_to_at_least(Item &item, int64_t min_capacity);
/* 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 {
GVectorArray *vector_array_;
GVectorArray_TypedMutableRef(GVectorArray &vector_array) : vector_array_(&vector_array)
BLI_assert(vector_array_->type().is<T>());
return vector_array_->size();
return vector_array_->is_empty();
void append(const int64_t index, const T &value)
vector_array_->append(index, &value);
void extend(const int64_t index, const Span<T> values)
vector_array_->extend(index, values);
void extend(const int64_t index, const VArray<T> &values)
MutableSpan<T> operator[](const int64_t index)
return (*vector_array_)[index].typed<T>();
/* A generic virtual vector array implementation for a `GVectorArray`. */
class GVVectorArray_For_GVectorArray : public GVVectorArray {
const GVectorArray &vector_array_;
GVVectorArray_For_GVectorArray(const GVectorArray &vector_array)
: GVVectorArray(vector_array.type(), vector_array.size()), vector_array_(vector_array)
protected:
int64_t get_vector_size_impl(const int64_t index) const override
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_assign(vector_array_[index][index_in_vector], r_value);
} // namespace blender