Changeset View
Changeset View
Standalone View
Standalone View
source/blender/functions/FN_field_cpp_type.hh
| /* SPDX-License-Identifier: GPL-2.0-or-later */ | /* SPDX-License-Identifier: GPL-2.0-or-later */ | ||||
| #pragma once | #pragma once | ||||
| /** \file | /** \file | ||||
| * \ingroup fn | * \ingroup fn | ||||
| */ | */ | ||||
| #include "BLI_cpp_type_make.hh" | |||||
| #include "FN_field.hh" | #include "FN_field.hh" | ||||
| namespace blender::fn { | namespace blender::fn { | ||||
| template<typename T> struct FieldCPPTypeParam { | /** | ||||
| }; | * Contains information about how to deal with a `ValueOrField<T>` generically. | ||||
| */ | |||||
| class FieldCPPType : public CPPType { | class ValueOrFieldCPPType { | ||||
| private: | |||||
| const CPPType &base_type_; | |||||
| public: | |||||
| template<typename T> | |||||
| FieldCPPType(FieldCPPTypeParam<Field<T>> /* unused */, StringRef debug_name) | |||||
| : CPPType(CPPTypeParam<Field<T>, CPPTypeFlags::None>(), debug_name), | |||||
| base_type_(CPPType::get<T>()) | |||||
| { | |||||
| } | |||||
| const CPPType &base_type() const | |||||
| { | |||||
| return base_type_; | |||||
| } | |||||
| /* Ensure that #GField and #Field<T> have the same layout, to enable casting between the two. */ | |||||
| static_assert(sizeof(Field<int>) == sizeof(GField)); | |||||
| static_assert(sizeof(Field<int>) == sizeof(Field<std::string>)); | |||||
| const GField &get_gfield(const void *field) const | |||||
| { | |||||
| return *(const GField *)field; | |||||
| } | |||||
| void construct_from_gfield(void *r_value, const GField &gfield) const | |||||
| { | |||||
| new (r_value) GField(gfield); | |||||
| } | |||||
| }; | |||||
| class ValueOrFieldCPPType : public CPPType { | |||||
| private: | private: | ||||
| const CPPType &base_type_; | |||||
| void (*construct_from_value_)(void *dst, const void *value); | void (*construct_from_value_)(void *dst, const void *value); | ||||
| void (*construct_from_field_)(void *dst, GField field); | void (*construct_from_field_)(void *dst, GField field); | ||||
| const void *(*get_value_ptr_)(const void *value_or_field); | const void *(*get_value_ptr_)(const void *value_or_field); | ||||
| const GField *(*get_field_ptr_)(const void *value_or_field); | const GField *(*get_field_ptr_)(const void *value_or_field); | ||||
| bool (*is_field_)(const void *value_or_field); | bool (*is_field_)(const void *value_or_field); | ||||
| GField (*as_field_)(const void *value_or_field); | GField (*as_field_)(const void *value_or_field); | ||||
| public: | public: | ||||
| template<typename T> | /** The #ValueOrField<T> itself. */ | ||||
| ValueOrFieldCPPType(FieldCPPTypeParam<ValueOrField<T>> /* unused */, StringRef debug_name) | const CPPType &self; | ||||
| : CPPType(CPPTypeParam<ValueOrField<T>, CPPTypeFlags::Printable>(), debug_name), | /** The type stored in the field. */ | ||||
| base_type_(CPPType::get<T>()) | const CPPType &value; | ||||
| { | |||||
| construct_from_value_ = [](void *dst, const void *value_or_field) { | |||||
| new (dst) ValueOrField<T>(*(const T *)value_or_field); | |||||
| }; | |||||
| construct_from_field_ = [](void *dst, GField field) { | |||||
| new (dst) ValueOrField<T>(Field<T>(std::move(field))); | |||||
| }; | |||||
| get_value_ptr_ = [](const void *value_or_field) { | |||||
| return (const void *)&((ValueOrField<T> *)value_or_field)->value; | |||||
| }; | |||||
| get_field_ptr_ = [](const void *value_or_field) -> const GField * { | |||||
| return &((ValueOrField<T> *)value_or_field)->field; | |||||
| }; | |||||
| is_field_ = [](const void *value_or_field) { | |||||
| return ((ValueOrField<T> *)value_or_field)->is_field(); | |||||
| }; | |||||
| as_field_ = [](const void *value_or_field) -> GField { | |||||
| return ((ValueOrField<T> *)value_or_field)->as_field(); | |||||
| }; | |||||
| } | |||||
| const CPPType &base_type() const | template<typename ValueType> ValueOrFieldCPPType(TypeTag<ValueType> /*value_type*/); | ||||
| { | |||||
| return base_type_; | |||||
| } | |||||
| void construct_from_value(void *dst, const void *value) const | void construct_from_value(void *dst, const void *value) const | ||||
| { | { | ||||
| construct_from_value_(dst, value); | construct_from_value_(dst, value); | ||||
| } | } | ||||
| void construct_from_field(void *dst, GField field) const | void construct_from_field(void *dst, GField field) const | ||||
| { | { | ||||
| Show All 20 Lines | public: | ||||
| { | { | ||||
| return is_field_(value_or_field); | return is_field_(value_or_field); | ||||
| } | } | ||||
| GField as_field(const void *value_or_field) const | GField as_field(const void *value_or_field) const | ||||
| { | { | ||||
| return as_field_(value_or_field); | return as_field_(value_or_field); | ||||
| } | } | ||||
| }; | |||||
| } // namespace blender::fn | /** | ||||
| * Try to find the #ValueOrFieldCPPType that corresponds to a #CPPType. | |||||
| */ | |||||
| static const ValueOrFieldCPPType *get_from_self(const CPPType &self); | |||||
| /** | |||||
| * Try to find the #ValueOrFieldCPPType that wraps a #ValueOrField containing the given value | |||||
| * type. This only works when the type has been created with #FN_FIELD_CPP_TYPE_MAKE. | |||||
| */ | |||||
| static const ValueOrFieldCPPType *get_from_value(const CPPType &value); | |||||
| #define MAKE_FIELD_CPP_TYPE(DEBUG_NAME, FIELD_TYPE) \ | template<typename ValueType> static const ValueOrFieldCPPType &get() | ||||
| template<> const blender::CPPType &blender::CPPType::get_impl<blender::fn::Field<FIELD_TYPE>>() \ | { | ||||
| { \ | static const ValueOrFieldCPPType &type = | ||||
| static blender::fn::FieldCPPType cpp_type{ \ | ValueOrFieldCPPType::get_impl<std::decay_t<ValueType>>(); | ||||
| blender::fn::FieldCPPTypeParam<blender::fn::Field<FIELD_TYPE>>(), STRINGIFY(DEBUG_NAME)}; \ | return type; | ||||
| return cpp_type; \ | |||||
| } \ | |||||
| template<> \ | |||||
| const blender::CPPType &blender::CPPType::get_impl<blender::fn::ValueOrField<FIELD_TYPE>>() \ | |||||
| { \ | |||||
| static blender::fn::ValueOrFieldCPPType cpp_type{ \ | |||||
| blender::fn::FieldCPPTypeParam<blender::fn::ValueOrField<FIELD_TYPE>>(), \ | |||||
| STRINGIFY(DEBUG_NAME##OrValue)}; \ | |||||
| return cpp_type; \ | |||||
| } | } | ||||
| private: | |||||
| template<typename ValueType> static const ValueOrFieldCPPType &get_impl(); | |||||
| void register_self(); | |||||
| }; | |||||
| } // namespace blender::fn | |||||