Geometry Nodes: deduplicate virtual array implementations

For some underlying data (e.g. spans) we had two virtual array
implementations. One for the mutable and one for the immutable
case. Now that most code does not deal with the virtual array
implementations directly anymore (since rBrBd4c868da9f97a),
we can get away with sharing one implementation for both cases.
This means that we have to do a `const_cast` in a few places, but
this is an implementation detail that does not leak into "user code"
(only when explicitly casting a `VArrayImpl` to a `VMutableArrayImpl`,
which should happen nowhere).
This commit is contained in:
Jacques Lucke 2021-11-26 14:47:02 +01:00
parent ef88047a97
commit f86331a033
6 changed files with 139 additions and 387 deletions

View File

@ -50,7 +50,7 @@ using blender::bke::AttributeIDRef;
using blender::bke::OutputAttribute;
using blender::fn::GMutableSpan;
using blender::fn::GSpan;
using blender::fn::GVMutableArrayImpl_For_GMutableSpan;
using blender::fn::GVArrayImpl_For_GSpan;
namespace blender::bke {
@ -1200,8 +1200,7 @@ blender::fn::GVArray GeometryComponent::attribute_get_for_read(const AttributeID
return blender::fn::GVArray::ForSingle(*type, domain_size, default_value);
}
class GVMutableAttribute_For_OutputAttribute
: public blender::fn::GVMutableArrayImpl_For_GMutableSpan {
class GVMutableAttribute_For_OutputAttribute : public blender::fn::GVArrayImpl_For_GSpan {
public:
GeometryComponent *component;
std::string attribute_name;
@ -1210,7 +1209,7 @@ class GVMutableAttribute_For_OutputAttribute
GVMutableAttribute_For_OutputAttribute(GMutableSpan data,
GeometryComponent &component,
const AttributeIDRef &attribute_id)
: blender::fn::GVMutableArrayImpl_For_GMutableSpan(data), component(&component)
: blender::fn::GVArrayImpl_For_GSpan(data), component(&component)
{
if (attribute_id.is_named()) {
this->attribute_name = attribute_id.name();

View File

@ -713,47 +713,16 @@ static bool remove_point_attribute(GeometryComponent &component,
return layer_freed;
}
/**
* Virtual array for any control point data accessed with spans and an offset array.
*/
template<typename T> class VArray_For_SplinePoints : public VArrayImpl<T> {
private:
const Array<Span<T>> data_;
Array<int> offsets_;
public:
VArray_For_SplinePoints(Array<Span<T>> data, Array<int> offsets)
: VArrayImpl<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets))
{
}
T get(const int64_t index) const final
{
const PointIndices indices = lookup_point_indices(offsets_, index);
return data_[indices.spline_index][indices.point_index];
}
void materialize(const IndexMask mask, MutableSpan<T> r_span) const final
{
point_attribute_materialize(data_.as_span(), offsets_, mask, r_span);
}
void materialize_to_uninitialized(const IndexMask mask, MutableSpan<T> r_span) const final
{
point_attribute_materialize_to_uninitialized(data_.as_span(), offsets_, mask, r_span);
}
};
/**
* Mutable virtual array for any control point data accessed with spans and an offset array.
*/
template<typename T> class VMutableArray_For_SplinePoints final : public VMutableArrayImpl<T> {
template<typename T> class VArrayImpl_For_SplinePoints final : public VMutableArrayImpl<T> {
private:
Array<MutableSpan<T>> data_;
Array<int> offsets_;
public:
VMutableArray_For_SplinePoints(Array<MutableSpan<T>> data, Array<int> offsets)
VArrayImpl_For_SplinePoints(Array<MutableSpan<T>> data, Array<int> offsets)
: VMutableArrayImpl<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets))
{
}
@ -791,16 +760,17 @@ template<typename T> class VMutableArray_For_SplinePoints final : public VMutabl
}
};
template<typename T> VArray<T> point_data_varray(Array<Span<T>> spans, Array<int> offsets)
template<typename T> VArray<T> point_data_varray(Array<MutableSpan<T>> spans, Array<int> offsets)
{
return VArray<T>::template For<VArray_For_SplinePoints<T>>(std::move(spans), std::move(offsets));
return VArray<T>::template For<VArrayImpl_For_SplinePoints<T>>(std::move(spans),
std::move(offsets));
}
template<typename T>
VMutableArray<T> point_data_varray(Array<MutableSpan<T>> spans, Array<int> offsets)
VMutableArray<T> point_data_varray_mutable(Array<MutableSpan<T>> spans, Array<int> offsets)
{
return VMutableArray<T>::template For<VMutableArray_For_SplinePoints<T>>(std::move(spans),
std::move(offsets));
return VMutableArray<T>::template For<VArrayImpl_For_SplinePoints<T>>(std::move(spans),
std::move(offsets));
}
/**
@ -811,13 +781,13 @@ VMutableArray<T> point_data_varray(Array<MutableSpan<T>> spans, Array<int> offse
* \note There is no need to check the handle type to avoid changing auto handles, since
* retrieving write access to the position data will mark them for recomputation anyway.
*/
class VMutableArray_For_SplinePosition final : public VMutableArrayImpl<float3> {
class VArrayImpl_For_SplinePosition final : public VMutableArrayImpl<float3> {
private:
MutableSpan<SplinePtr> splines_;
Array<int> offsets_;
public:
VMutableArray_For_SplinePosition(MutableSpan<SplinePtr> splines, Array<int> offsets)
VArrayImpl_For_SplinePosition(MutableSpan<SplinePtr> splines, Array<int> offsets)
: VMutableArrayImpl<float3>(offsets.last()), splines_(splines), offsets_(std::move(offsets))
{
}
@ -889,104 +859,16 @@ class VMutableArray_For_SplinePosition final : public VMutableArrayImpl<float3>
}
};
class VArray_For_BezierHandle final : public VArrayImpl<float3> {
private:
Span<SplinePtr> splines_;
Array<int> offsets_;
bool is_right_;
public:
VArray_For_BezierHandle(Span<SplinePtr> splines, Array<int> offsets, const bool is_right)
: VArrayImpl<float3>(offsets.last()),
splines_(std::move(splines)),
offsets_(std::move(offsets)),
is_right_(is_right)
{
}
static float3 get_internal(const int64_t index,
Span<SplinePtr> splines,
Span<int> offsets,
const bool is_right)
{
const PointIndices indices = lookup_point_indices(offsets, index);
const Spline &spline = *splines[indices.spline_index];
if (spline.type() == Spline::Type::Bezier) {
const BezierSpline &bezier_spline = static_cast<const BezierSpline &>(spline);
return is_right ? bezier_spline.handle_positions_right()[indices.point_index] :
bezier_spline.handle_positions_left()[indices.point_index];
}
return float3(0);
}
float3 get(const int64_t index) const final
{
return get_internal(index, splines_, offsets_, is_right_);
}
/**
* Utility so we can pass handle positions to the materialize functions above.
*
* \note This relies on the ability of the materialize implementations to
* handle empty spans, since only Bezier splines have handles.
*/
static Array<Span<float3>> get_handle_spans(Span<SplinePtr> splines, const bool is_right)
{
Array<Span<float3>> spans(splines.size());
for (const int i : spans.index_range()) {
if (splines[i]->type() == Spline::Type::Bezier) {
BezierSpline &bezier_spline = static_cast<BezierSpline &>(*splines[i]);
spans[i] = is_right ? bezier_spline.handle_positions_right() :
bezier_spline.handle_positions_left();
}
else {
spans[i] = {};
}
}
return spans;
}
static void materialize_internal(const IndexMask mask,
Span<SplinePtr> splines,
Span<int> offsets,
const bool is_right,
MutableSpan<float3> r_span)
{
Array<Span<float3>> spans = get_handle_spans(splines, is_right);
point_attribute_materialize(spans.as_span(), offsets, mask, r_span);
}
static void materialize_to_uninitialized_internal(const IndexMask mask,
Span<SplinePtr> splines,
Span<int> offsets,
const bool is_right,
MutableSpan<float3> r_span)
{
Array<Span<float3>> spans = get_handle_spans(splines, is_right);
point_attribute_materialize_to_uninitialized(spans.as_span(), offsets, mask, r_span);
}
void materialize(const IndexMask mask, MutableSpan<float3> r_span) const final
{
materialize_internal(mask, splines_, offsets_, is_right_, r_span);
}
void materialize_to_uninitialized(const IndexMask mask, MutableSpan<float3> r_span) const final
{
materialize_to_uninitialized_internal(mask, splines_, offsets_, is_right_, r_span);
}
};
class VMutableArray_For_BezierHandles final : public VMutableArrayImpl<float3> {
class VArrayImpl_For_BezierHandles final : public VMutableArrayImpl<float3> {
private:
MutableSpan<SplinePtr> splines_;
Array<int> offsets_;
bool is_right_;
public:
VMutableArray_For_BezierHandles(MutableSpan<SplinePtr> splines,
Array<int> offsets,
const bool is_right)
VArrayImpl_For_BezierHandles(MutableSpan<SplinePtr> splines,
Array<int> offsets,
const bool is_right)
: VMutableArrayImpl<float3>(offsets.last()),
splines_(splines),
offsets_(std::move(offsets)),
@ -996,7 +878,14 @@ class VMutableArray_For_BezierHandles final : public VMutableArrayImpl<float3> {
float3 get(const int64_t index) const final
{
return VArray_For_BezierHandle::get_internal(index, splines_, offsets_, is_right_);
const PointIndices indices = lookup_point_indices(offsets_, index);
const Spline &spline = *splines_[indices.spline_index];
if (spline.type() == Spline::Type::Bezier) {
const BezierSpline &bezier_spline = static_cast<const BezierSpline &>(spline);
return is_right_ ? bezier_spline.handle_positions_right()[indices.point_index] :
bezier_spline.handle_positions_left()[indices.point_index];
}
return float3(0);
}
void set(const int64_t index, float3 value) final
@ -1040,13 +929,36 @@ class VMutableArray_For_BezierHandles final : public VMutableArrayImpl<float3> {
void materialize(const IndexMask mask, MutableSpan<float3> r_span) const final
{
VArray_For_BezierHandle::materialize_internal(mask, splines_, offsets_, is_right_, r_span);
Array<Span<float3>> spans = get_handle_spans(splines_, is_right_);
point_attribute_materialize(spans.as_span(), offsets_, mask, r_span);
}
void materialize_to_uninitialized(const IndexMask mask, MutableSpan<float3> r_span) const final
{
VArray_For_BezierHandle::materialize_to_uninitialized_internal(
mask, splines_, offsets_, is_right_, r_span);
Array<Span<float3>> spans = get_handle_spans(splines_, is_right_);
point_attribute_materialize_to_uninitialized(spans.as_span(), offsets_, mask, r_span);
}
/**
* Utility so we can pass handle positions to the materialize functions above.
*
* \note This relies on the ability of the materialize implementations to
* handle empty spans, since only Bezier splines have handles.
*/
static Array<Span<float3>> get_handle_spans(Span<SplinePtr> splines, const bool is_right)
{
Array<Span<float3>> spans(splines.size());
for (const int i : spans.index_range()) {
if (splines[i]->type() == Spline::Type::Bezier) {
BezierSpline &bezier_spline = static_cast<BezierSpline &>(*splines[i]);
spans[i] = is_right ? bezier_spline.handle_positions_right() :
bezier_spline.handle_positions_left();
}
else {
spans[i] = {};
}
}
return spans;
}
};
@ -1102,9 +1014,12 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu
}
Array<int> offsets = curve->control_point_offsets();
Array<Span<T>> spans(splines.size());
Array<MutableSpan<T>> spans(splines.size());
for (const int i : splines.index_range()) {
spans[i] = get_span_(*splines[i]);
Span<T> span = get_span_(*splines[i]);
/* Use const-cast because the underlying virtual array implementation is shared between const
* and non const data. */
spans[i] = MutableSpan<T>(const_cast<T *>(span.data()), span.size());
}
return point_data_varray(spans, offsets);
@ -1143,7 +1058,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu
spans[i] = get_mutable_span_(*splines[i]);
}
return {point_data_varray(spans, offsets), domain_, tag_modified_fn};
return {point_data_varray_mutable(spans, offsets), domain_, tag_modified_fn};
}
bool try_delete(GeometryComponent &component) const final
@ -1235,8 +1150,8 @@ class PositionAttributeProvider final : public BuiltinPointAttributeProvider<flo
};
Array<int> offsets = curve->control_point_offsets();
return {VMutableArray<float3>::For<VMutableArray_For_SplinePosition>(curve->splines(),
std::move(offsets)),
return {VMutableArray<float3>::For<VArrayImpl_For_SplinePosition>(curve->splines(),
std::move(offsets)),
domain_,
tag_modified_fn};
}
@ -1270,8 +1185,10 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider {
}
Array<int> offsets = curve->control_point_offsets();
return VArray<float3>::For<VArray_For_BezierHandle>(
curve->splines(), std::move(offsets), is_right_);
/* Use const-cast because the underlying virtual array implementation is shared between const
* and non const data. */
return VArray<float3>::For<VArrayImpl_For_BezierHandles>(
const_cast<CurveEval *>(curve)->splines(), std::move(offsets), is_right_);
}
WriteAttributeLookup try_get_for_write(GeometryComponent &component) const override
@ -1288,7 +1205,7 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider {
auto tag_modified_fn = [curve]() { curve->mark_cache_invalid(); };
Array<int> offsets = curve->control_point_offsets();
return {VMutableArray<float3>::For<VMutableArray_For_BezierHandles>(
return {VMutableArray<float3>::For<VArrayImpl_For_BezierHandles>(
curve->splines(), std::move(offsets), is_right_),
domain_,
tag_modified_fn};
@ -1377,9 +1294,12 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
Array<int> offsets = curve->control_point_offsets();
attribute_math::convert_to_static_type(spans[0].type(), [&](auto dummy) {
using T = decltype(dummy);
Array<Span<T>> data(splines.size());
Array<MutableSpan<T>> data(splines.size());
for (const int i : splines.index_range()) {
data[i] = spans[i].typed<T>();
Span<T> span = spans[i].typed<T>();
/* Use const-cast because the underlying virtual array implementation is shared between
* const and non const data. */
data[i] = MutableSpan<T>(const_cast<T *>(span.data()), span.size());
BLI_assert(data[i].data() != nullptr);
}
attribute = {point_data_varray(data, offsets), ATTR_DOMAIN_POINT};
@ -1435,7 +1355,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
data[i] = spans[i].typed<T>();
BLI_assert(data[i].data() != nullptr);
}
attribute = {point_data_varray(data, offsets), ATTR_DOMAIN_POINT};
attribute = {point_data_varray_mutable(data, offsets), ATTR_DOMAIN_POINT};
});
return attribute;
}

View File

@ -996,20 +996,30 @@ static void set_crease(MEdge &edge, float value)
edge.crease = round_fl_to_uchar_clamp(value * 255.0f);
}
class VMutableArray_For_VertexWeights final : public VMutableArrayImpl<float> {
class VArrayImpl_For_VertexWeights final : public VMutableArrayImpl<float> {
private:
MDeformVert *dverts_;
const int dvert_index_;
public:
VMutableArray_For_VertexWeights(MDeformVert *dverts, const int totvert, const int dvert_index)
VArrayImpl_For_VertexWeights(MDeformVert *dverts, const int totvert, const int dvert_index)
: VMutableArrayImpl<float>(totvert), dverts_(dverts), dvert_index_(dvert_index)
{
}
float get(const int64_t index) const override
{
return get_internal(dverts_, dvert_index_, index);
if (dverts_ == nullptr) {
return 0.0f;
}
const MDeformVert &dvert = dverts_[index];
for (const MDeformWeight &weight : Span(dvert.dw, dvert.totweight)) {
if (weight.def_nr == dvert_index_) {
return weight.weight;
}
}
return 0.0f;
;
}
void set(const int64_t index, const float value) override
@ -1017,37 +1027,6 @@ class VMutableArray_For_VertexWeights final : public VMutableArrayImpl<float> {
MDeformWeight *weight = BKE_defvert_ensure_index(&dverts_[index], dvert_index_);
weight->weight = value;
}
static float get_internal(const MDeformVert *dverts, const int dvert_index, const int64_t index)
{
if (dverts == nullptr) {
return 0.0f;
}
const MDeformVert &dvert = dverts[index];
for (const MDeformWeight &weight : Span(dvert.dw, dvert.totweight)) {
if (weight.def_nr == dvert_index) {
return weight.weight;
}
}
return 0.0f;
}
};
class VArray_For_VertexWeights final : public VArrayImpl<float> {
private:
const MDeformVert *dverts_;
const int dvert_index_;
public:
VArray_For_VertexWeights(const MDeformVert *dverts, const int totvert, const int dvert_index)
: VArrayImpl<float>(totvert), dverts_(dverts), dvert_index_(dvert_index)
{
}
float get(const int64_t index) const override
{
return VMutableArray_For_VertexWeights::get_internal(dverts_, dvert_index_, index);
}
};
/**
@ -1077,7 +1056,7 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider {
static const float default_value = 0.0f;
return {VArray<float>::ForSingle(default_value, mesh->totvert), ATTR_DOMAIN_POINT};
}
return {VArray<float>::For<VArray_For_VertexWeights>(
return {VArray<float>::For<VArrayImpl_For_VertexWeights>(
mesh->dvert, mesh->totvert, vertex_group_index),
ATTR_DOMAIN_POINT};
}
@ -1109,7 +1088,7 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider {
mesh->dvert = (MDeformVert *)CustomData_duplicate_referenced_layer(
&mesh->vdata, CD_MDEFORMVERT, mesh->totvert);
}
return {VMutableArray<float>::For<VMutableArray_For_VertexWeights>(
return {VMutableArray<float>::For<VArrayImpl_For_VertexWeights>(
mesh->dvert, mesh->totvert, vertex_group_index),
ATTR_DOMAIN_POINT};
}

View File

@ -223,69 +223,21 @@ template<typename T> class VMutableArrayImpl : public VArrayImpl<T> {
};
/**
* A virtual array implementation for a span. Methods in this class are final so that it can be
* devirtualized by the compiler in some cases (e.g. when #devirtualize_varray is used).
* A virtual array implementation that references that wraps a span. This implementation is used by
* mutable and immutable spans to avoid code duplication.
*/
template<typename T> class VArrayImpl_For_Span : public VArrayImpl<T> {
protected:
const T *data_ = nullptr;
public:
VArrayImpl_For_Span(const Span<T> data) : VArrayImpl<T>(data.size()), data_(data.data())
{
}
protected:
VArrayImpl_For_Span(const int64_t size) : VArrayImpl<T>(size)
{
}
T get(const int64_t index) const final
{
return data_[index];
}
bool is_span() const final
{
return true;
}
Span<T> get_internal_span() const final
{
return Span<T>(data_, this->size_);
}
};
/**
* A version of #VArrayImpl_For_Span that can not be subclassed. This allows safely overwriting the
* #may_have_ownership method.
*/
template<typename T> class VArrayImpl_For_Span_final final : public VArrayImpl_For_Span<T> {
public:
using VArrayImpl_For_Span<T>::VArrayImpl_For_Span;
private:
bool may_have_ownership() const override
{
return false;
}
};
/**
* Like #VArrayImpl_For_Span but for mutable data.
*/
template<typename T> class VMutableArrayImpl_For_MutableSpan : public VMutableArrayImpl<T> {
template<typename T> class VArrayImpl_For_Span : public VMutableArrayImpl<T> {
protected:
T *data_ = nullptr;
public:
VMutableArrayImpl_For_MutableSpan(const MutableSpan<T> data)
VArrayImpl_For_Span(const MutableSpan<T> data)
: VMutableArrayImpl<T>(data.size()), data_(data.data())
{
}
protected:
VMutableArrayImpl_For_MutableSpan(const int64_t size) : VMutableArrayImpl<T>(size)
VArrayImpl_For_Span(const int64_t size) : VMutableArrayImpl<T>(size)
{
}
@ -311,12 +263,12 @@ template<typename T> class VMutableArrayImpl_For_MutableSpan : public VMutableAr
};
/**
* Like #VArrayImpl_For_Span_final but for mutable data.
* A version of #VArrayImpl_For_Span that can not be subclassed. This allows safely overwriting the
* #may_have_ownership method.
*/
template<typename T>
class VMutableArrayImpl_For_MutableSpan_final final : public VMutableArrayImpl_For_MutableSpan<T> {
template<typename T> class VArrayImpl_For_Span_final final : public VArrayImpl_For_Span<T> {
public:
using VMutableArrayImpl_For_MutableSpan<T>::VMutableArrayImpl_For_MutableSpan;
using VArrayImpl_For_Span<T>::VArrayImpl_For_Span;
private:
bool may_have_ownership() const override
@ -340,7 +292,7 @@ class VArrayImpl_For_ArrayContainer : public VArrayImpl_For_Span<T> {
VArrayImpl_For_ArrayContainer(Container container)
: VArrayImpl_For_Span<T>((int64_t)container.size()), container_(std::move(container))
{
this->data_ = container_.data();
this->data_ = const_cast<T *>(container_.data());
}
};
@ -419,57 +371,19 @@ template<typename T, typename GetFunc> class VArrayImpl_For_Func final : public
}
};
/**
* \note: This is `final` so that #may_have_ownership can be implemented reliably.
*/
template<typename StructT, typename ElemT, ElemT (*GetFunc)(const StructT &)>
class VArrayImpl_For_DerivedSpan final : public VArrayImpl<ElemT> {
private:
const StructT *data_;
public:
VArrayImpl_For_DerivedSpan(const Span<StructT> data)
: VArrayImpl<ElemT>(data.size()), data_(data.data())
{
}
private:
ElemT get(const int64_t index) const override
{
return GetFunc(data_[index]);
}
void materialize(IndexMask mask, MutableSpan<ElemT> r_span) const override
{
ElemT *dst = r_span.data();
mask.foreach_index([&](const int64_t i) { dst[i] = GetFunc(data_[i]); });
}
void materialize_to_uninitialized(IndexMask mask, MutableSpan<ElemT> r_span) const override
{
ElemT *dst = r_span.data();
mask.foreach_index([&](const int64_t i) { new (dst + i) ElemT(GetFunc(data_[i])); });
}
bool may_have_ownership() const override
{
return false;
}
};
/**
* \note: This is `final` so that #may_have_ownership can be implemented reliably.
*/
template<typename StructT,
typename ElemT,
ElemT (*GetFunc)(const StructT &),
void (*SetFunc)(StructT &, ElemT)>
class VMutableArrayImpl_For_DerivedSpan final : public VMutableArrayImpl<ElemT> {
void (*SetFunc)(StructT &, ElemT) = nullptr>
class VArrayImpl_For_DerivedSpan final : public VMutableArrayImpl<ElemT> {
private:
StructT *data_;
public:
VMutableArrayImpl_For_DerivedSpan(const MutableSpan<StructT> data)
VArrayImpl_For_DerivedSpan(const MutableSpan<StructT> data)
: VMutableArrayImpl<ElemT>(data.size()), data_(data.data())
{
}
@ -482,6 +396,7 @@ class VMutableArrayImpl_For_DerivedSpan final : public VMutableArrayImpl<ElemT>
void set(const int64_t index, ElemT value) override
{
BLI_assert(SetFunc != nullptr);
SetFunc(data_[index], std::move(value));
}
@ -840,7 +755,10 @@ template<typename T> class VArray : public VArrayCommon<T> {
*/
static VArray ForSpan(Span<T> values)
{
return VArray::For<VArrayImpl_For_Span_final<T>>(values);
/* Cast const away, because the virtual array implementation for const and non const spans is
* shared. */
MutableSpan<T> span{const_cast<T *>(values.data()), values.size()};
return VArray::For<VArrayImpl_For_Span_final<T>>(span);
}
/**
@ -859,7 +777,10 @@ template<typename T> class VArray : public VArrayCommon<T> {
template<typename StructT, T (*GetFunc)(const StructT &)>
static VArray ForDerivedSpan(Span<StructT> values)
{
return VArray::For<VArrayImpl_For_DerivedSpan<StructT, T, GetFunc>>(values);
/* Cast const away, because the virtual array implementation for const and non const derived
* spans is shared. */
MutableSpan<StructT> span{const_cast<StructT *>(values.data()), values.size()};
return VArray::For<VArrayImpl_For_DerivedSpan<StructT, T, GetFunc>>(span);
}
/**
@ -919,7 +840,7 @@ template<typename T> class VMutableArray : public VArrayCommon<T> {
*/
static VMutableArray ForSpan(MutableSpan<T> values)
{
return VMutableArray::For<VMutableArrayImpl_For_MutableSpan_final<T>>(values);
return VMutableArray::For<VArrayImpl_For_Span_final<T>>(values);
}
/**
@ -929,8 +850,7 @@ template<typename T> class VMutableArray : public VArrayCommon<T> {
template<typename StructT, T (*GetFunc)(const StructT &), void (*SetFunc)(StructT &, T)>
static VMutableArray ForDerivedSpan(MutableSpan<StructT> values)
{
return VMutableArray::For<VMutableArrayImpl_For_DerivedSpan<StructT, T, GetFunc, SetFunc>>(
values);
return VMutableArray::For<VArrayImpl_For_DerivedSpan<StructT, T, GetFunc, SetFunc>>(values);
}
/** Convert to a #VArray by copying. */

View File

@ -555,37 +555,19 @@ template<typename T> class VMutableArrayImpl_For_GVMutableArray : public VMutabl
/** \} */
/* -------------------------------------------------------------------- */
/** \name #GVArrayImpl_For_GSpan and #GVMutableArrayImpl_For_GMutableSpan.
/** \name #GVArrayImpl_For_GSpan.
* \{ */
class GVArrayImpl_For_GSpan : public GVArrayImpl {
protected:
const void *data_ = nullptr;
const int64_t element_size_;
public:
GVArrayImpl_For_GSpan(const GSpan span);
protected:
GVArrayImpl_For_GSpan(const CPPType &type, const int64_t size);
void get(const int64_t index, void *r_value) const override;
void get_to_uninitialized(const int64_t index, void *r_value) const override;
bool is_span() const override;
GSpan get_internal_span() const override;
};
class GVMutableArrayImpl_For_GMutableSpan : public GVMutableArrayImpl {
class GVArrayImpl_For_GSpan : public GVMutableArrayImpl {
protected:
void *data_ = nullptr;
const int64_t element_size_;
public:
GVMutableArrayImpl_For_GMutableSpan(const GMutableSpan span);
GVArrayImpl_For_GSpan(const GMutableSpan span);
protected:
GVMutableArrayImpl_For_GMutableSpan(const CPPType &type, const int64_t size);
GVArrayImpl_For_GSpan(const CPPType &type, const int64_t size);
public:
void get(const int64_t index, void *r_value) const override;

View File

@ -139,13 +139,15 @@ bool GVMutableArrayImpl::try_assign_VMutableArray(void *UNUSED(varray)) const
/** \name #GVArrayImpl_For_GSpan
* \{ */
GVArrayImpl_For_GSpan::GVArrayImpl_For_GSpan(const GSpan span)
: GVArrayImpl(span.type(), span.size()), data_(span.data()), element_size_(span.type().size())
GVArrayImpl_For_GSpan::GVArrayImpl_For_GSpan(const GMutableSpan span)
: GVMutableArrayImpl(span.type(), span.size()),
data_(span.data()),
element_size_(span.type().size())
{
}
GVArrayImpl_For_GSpan::GVArrayImpl_For_GSpan(const CPPType &type, const int64_t size)
: GVArrayImpl(type, size), element_size_(type.size())
: GVMutableArrayImpl(type, size), element_size_(type.size())
{
}
@ -159,6 +161,21 @@ void GVArrayImpl_For_GSpan::get_to_uninitialized(const int64_t index, void *r_va
type_->copy_construct(POINTER_OFFSET(data_, element_size_ * index), r_value);
}
void GVArrayImpl_For_GSpan::set_by_copy(const int64_t index, const void *value)
{
type_->copy_assign(value, POINTER_OFFSET(data_, element_size_ * index));
}
void GVArrayImpl_For_GSpan::set_by_move(const int64_t index, void *value)
{
type_->move_construct(value, POINTER_OFFSET(data_, element_size_ * index));
}
void GVArrayImpl_For_GSpan::set_by_relocate(const int64_t index, void *value)
{
type_->relocate_assign(value, POINTER_OFFSET(data_, element_size_ * index));
}
bool GVArrayImpl_For_GSpan::is_span() const
{
return true;
@ -169,7 +186,6 @@ GSpan GVArrayImpl_For_GSpan::get_internal_span() const
return GSpan(*type_, data_, size_);
}
/** See #VArrayImpl_For_Span_final. */
class GVArrayImpl_For_GSpan_final final : public GVArrayImpl_For_GSpan {
public:
using GVArrayImpl_For_GSpan::GVArrayImpl_For_GSpan;
@ -183,73 +199,6 @@ class GVArrayImpl_For_GSpan_final final : public GVArrayImpl_For_GSpan {
/** \} */
/* -------------------------------------------------------------------- */
/** \name #GVMutableArrayImpl_For_GMutableSpan
* \{ */
GVMutableArrayImpl_For_GMutableSpan::GVMutableArrayImpl_For_GMutableSpan(const GMutableSpan span)
: GVMutableArrayImpl(span.type(), span.size()),
data_(span.data()),
element_size_(span.type().size())
{
}
GVMutableArrayImpl_For_GMutableSpan::GVMutableArrayImpl_For_GMutableSpan(const CPPType &type,
const int64_t size)
: GVMutableArrayImpl(type, size), element_size_(type.size())
{
}
void GVMutableArrayImpl_For_GMutableSpan::get(const int64_t index, void *r_value) const
{
type_->copy_assign(POINTER_OFFSET(data_, element_size_ * index), r_value);
}
void GVMutableArrayImpl_For_GMutableSpan::get_to_uninitialized(const int64_t index,
void *r_value) const
{
type_->copy_construct(POINTER_OFFSET(data_, element_size_ * index), r_value);
}
void GVMutableArrayImpl_For_GMutableSpan::set_by_copy(const int64_t index, const void *value)
{
type_->copy_assign(value, POINTER_OFFSET(data_, element_size_ * index));
}
void GVMutableArrayImpl_For_GMutableSpan::set_by_move(const int64_t index, void *value)
{
type_->move_construct(value, POINTER_OFFSET(data_, element_size_ * index));
}
void GVMutableArrayImpl_For_GMutableSpan::set_by_relocate(const int64_t index, void *value)
{
type_->relocate_assign(value, POINTER_OFFSET(data_, element_size_ * index));
}
bool GVMutableArrayImpl_For_GMutableSpan::is_span() const
{
return true;
}
GSpan GVMutableArrayImpl_For_GMutableSpan::get_internal_span() const
{
return GSpan(*type_, data_, size_);
}
class GVMutableArrayImpl_For_GMutableSpan_final final
: public GVMutableArrayImpl_For_GMutableSpan {
public:
using GVMutableArrayImpl_For_GMutableSpan::GVMutableArrayImpl_For_GMutableSpan;
private:
bool may_have_ownership() const override
{
return false;
}
};
/** \} */
/* -------------------------------------------------------------------- */
/** \name #GVArrayImpl_For_SingleValueRef
* \{ */
@ -682,7 +631,10 @@ GVArray GVArray::ForSingleDefault(const CPPType &type, const int64_t size)
GVArray GVArray::ForSpan(GSpan span)
{
return GVArray::For<GVArrayImpl_For_GSpan_final>(span);
/* Use const-cast because the underlying virtual array implementation is shared between const
* and non const data. */
GMutableSpan mutable_span{span.type(), const_cast<void *>(span.data()), span.size()};
return GVArray::For<GVArrayImpl_For_GSpan_final>(mutable_span);
}
class GVArrayImpl_For_GArray : public GVArrayImpl_For_GSpan {
@ -691,7 +643,7 @@ class GVArrayImpl_For_GArray : public GVArrayImpl_For_GSpan {
public:
GVArrayImpl_For_GArray(GArray<> array)
: GVArrayImpl_For_GSpan(array.as_span()), array_(std::move(array))
: GVArrayImpl_For_GSpan(array.as_mutable_span()), array_(std::move(array))
{
}
};
@ -743,7 +695,7 @@ GVMutableArray::GVMutableArray(std::shared_ptr<GVMutableArrayImpl> impl)
GVMutableArray GVMutableArray::ForSpan(GMutableSpan span)
{
return GVMutableArray::For<GVMutableArrayImpl_For_GMutableSpan_final>(span);
return GVMutableArray::For<GVArrayImpl_For_GSpan_final>(span);
}
GVMutableArray::operator GVArray() const &