From ce315cb3fefb229fa4997bca9dccdc3329148fa6 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 28 Jul 2024 09:21:23 +0200 Subject: entity: split into more headers --- entity/accessor.hpp | 12 +-- entity/concepts.hpp | 1 - entity/field-status.hpp | 7 ++ entity/field.hpp | 163 ++++++++++++++++++++++++++++++++++++++++ entity/metadata.hpp | 194 +++++------------------------------------------- 5 files changed, 189 insertions(+), 188 deletions(-) create mode 100644 entity/field-status.hpp create mode 100644 entity/field.hpp diff --git a/entity/accessor.hpp b/entity/accessor.hpp index 9dd9c3b6..ccfb5b13 100644 --- a/entity/accessor.hpp +++ b/entity/accessor.hpp @@ -2,21 +2,11 @@ #include "util.hpp" #include "erased-constraints.hpp" #include "name-of.hpp" -#include +#include "field-status.hpp" #include -namespace floormat::erased_constraints { - -struct range; -struct max_length; -struct group; - -} // namespace floormat::erased_constraints - namespace floormat::entities { -enum class field_status : unsigned char { hidden, readonly, enabled, COUNT, }; - struct erased_accessor final { using reader_t = void; using writer_t = void; diff --git a/entity/concepts.hpp b/entity/concepts.hpp index 5e01fcda..6c13299c 100644 --- a/entity/concepts.hpp +++ b/entity/concepts.hpp @@ -3,7 +3,6 @@ #include "compat/function2.hpp" #include "compat/assert.hpp" #include -#include namespace floormat::entities { diff --git a/entity/field-status.hpp b/entity/field-status.hpp new file mode 100644 index 00000000..f95d54ed --- /dev/null +++ b/entity/field-status.hpp @@ -0,0 +1,7 @@ +#pragma once + +namespace floormat::entities { + +enum class field_status : unsigned char { hidden, readonly, enabled, COUNT, }; + +} // namespace floormat::entities diff --git a/entity/field.hpp b/entity/field.hpp new file mode 100644 index 00000000..9b7e55b1 --- /dev/null +++ b/entity/field.hpp @@ -0,0 +1,163 @@ +#pragma once + +#include "constraints.hpp" +#include "concepts.hpp" +#include "accessor.hpp" +#include "field-status.hpp" +#include "compat/defs.hpp" + +namespace floormat::entities::detail { +template struct find_reader; + +template struct find_reader { + using type = Default; + static constexpr size_t index = I; +}; + +template +struct find_reader { + using type = typename find_reader::type; + static constexpr size_t index = find_reader::index; +}; + +template +requires FieldReader +struct find_reader { using type = F; static constexpr size_t index = I; }; + +} // namespace floormat::entities::detail + +namespace floormat::entities { + +constexpr auto constantly(const auto& x) noexcept { + return [x] (const Ts&...) constexpr -> const auto& { return x; }; +} + +template struct entity_field_base {}; + +template R, FieldWriter W, typename... Ts> +struct entity_field : entity_field_base { +private: + static constexpr auto default_predicate = constantly(field_status::enabled); + static constexpr auto default_c_range = constantly(constraints::range{}); + static constexpr auto default_c_length = constantly(constraints::max_length{size_t(-1)}); + using default_predicate_t = std::decay_t; + using default_c_range_t = std::decay_t; + using default_c_length_t = std::decay_t; + using c_predicate = detail::find_reader; + using c_range = detail::find_reader, default_c_range_t, 0, Ts...>; + using c_length = detail::find_reader; + static constexpr size_t good_arguments = + unsigned(c_predicate::index != sizeof...(Ts)) + + unsigned(c_range::index != sizeof...(Ts)) + + unsigned(c_length::index != sizeof...(Ts)); + static_assert(sizeof...(Ts) == good_arguments, "ignored arguments"); + +public: + using ObjectType = Obj; + using FieldType = Type; + using Reader = R; + using Writer = W; + using Predicate = typename c_predicate::type; + using Range = typename c_range::type; + using Length = typename c_length::type; + + StringView name; + [[fm_no_unique_address]] R reader; + [[fm_no_unique_address]] W writer; + [[fm_no_unique_address]] Predicate predicate; + [[fm_no_unique_address]] Range range; + [[fm_no_unique_address]] Length length; + + fm_DECLARE_DEFAULT_MOVE_COPY_ASSIGNMENTS(entity_field); + + static constexpr decltype(auto) read(const R& reader, const Obj& x) { return detail::read_field::read(x, reader); } + static constexpr void write(const W& writer, Obj& x, Type v); + constexpr decltype(auto) read(const Obj& x) const { return read(reader, x); } + constexpr void write(Obj& x, Type value) const { write(writer, x, move(value)); } + static constexpr bool can_write = !std::is_same_v::writer)>; + + static constexpr field_status is_enabled(const Predicate & p, const Obj& x); + constexpr field_status is_enabled(const Obj& x) const { return is_enabled(predicate, x); } + + static constexpr constraints::range get_range(const Range& r, const Obj& x); + constexpr constraints::range get_range(const Obj& x) const { return get_range(range, x); } + static constexpr constraints::max_length get_max_length(const Length& l, const Obj& x); + constexpr constraints::max_length get_max_length(const Obj& x) const { return get_max_length(length, x); } + + constexpr entity_field(StringView name, R r, W w, Ts&&... ts) noexcept : + name{name}, reader{r}, writer{w}, + predicate { std::get(std::forward_as_tuple(ts..., default_predicate)) }, + range { std::get (std::forward_as_tuple(ts..., default_c_range)) }, + length { std::get (std::forward_as_tuple(ts..., default_c_length)) } + {} + constexpr erased_accessor erased() const; +}; + +template R, FieldWriter W, typename... Ts> +constexpr void entity_field::write(const W& writer, Obj& x, Type v) +{ + static_assert(can_write); detail::write_field::write(x, writer, move(v)); +} + +template R, FieldWriter W, typename... Ts> +constexpr erased_accessor entity_field::erased() const +{ + using reader_t = typename erased_accessor::reader_t; + using writer_t = typename erased_accessor::writer_t; + using predicate_t = typename erased_accessor::predicate_t; + using c_range_t = typename erased_accessor::c_range_t; + using c_length_t = typename erased_accessor::c_length_t; + constexpr auto obj_name = name_of, field_name = name_of; + + constexpr auto reader_fn = [](const void* obj, const reader_t* reader, void* value) { + const auto& obj_ = *static_cast(obj); + const auto& reader_ = *static_cast(reader); + auto& value_ = *static_cast(value); + value_ = read(reader_, obj_); + }; + constexpr auto writer_fn = [](void* obj, const writer_t* writer, void* value) { + auto& obj_ = *static_cast(obj); + const auto& writer_ = *static_cast(writer); + Type value_ = move(*static_cast(value)); + write(writer_, obj_, move(value_)); + }; + constexpr auto predicate_fn = [](const void* obj, const predicate_t* predicate) { + const auto& obj_ = *static_cast(obj); + const auto& predicate_ = *static_cast(predicate); + return is_enabled(predicate_, obj_); + }; + constexpr auto writer_stub_fn = [](void*, const writer_t*, void*) { + fm_abort("no writer for this accessor"); + }; + constexpr bool has_writer = !std::is_same_v, std::nullptr_t>; + + constexpr auto c_range_fn = [](const void* obj, const c_range_t* reader) -> erased_constraints::range { + return get_range(*static_cast(reader), *reinterpret_cast(obj)); + }; + constexpr auto c_length_fn = [](const void* obj, const c_length_t* reader) -> erased_constraints::max_length { + return get_max_length(*static_cast(reader), *reinterpret_cast(obj)); + }; + return erased_accessor { + (void*)&reader, has_writer ? (void*)&writer : nullptr, + (void*)&predicate, + (void*)&range, (void*)&length, + name, obj_name, field_name, + reader_fn, has_writer ? writer_fn : writer_stub_fn, + predicate_fn, + c_range_fn, c_length_fn, + }; +} + +template R, FieldWriter W, typename... Ts> +constexpr field_status entity_field::is_enabled(const Predicate& p, const Obj& x) +{ return detail::read_field::read(x, p); } + +template R, FieldWriter W, typename... Ts> +constexpr constraints::range entity_field::get_range(const Range& r, const Obj& x) +{ return detail::read_field, Range>::read(x, r); } + +template R, FieldWriter W, typename... Ts> +constexpr constraints::max_length entity_field::get_max_length(const Length& l, const Obj& x) +{ return detail::read_field::read(x, l); } + +} // namespace floormat::entities diff --git a/entity/metadata.hpp b/entity/metadata.hpp index aa0fef95..8e3b41d3 100644 --- a/entity/metadata.hpp +++ b/entity/metadata.hpp @@ -1,28 +1,13 @@ #pragma once #include "name-of.hpp" #include "accessor.hpp" -#include "constraints.hpp" -#include "util.hpp" +#include "field.hpp" #include "concepts.hpp" -#include "compat/defs.hpp" -#include -#include -#include -#include +#include #include #include #include -namespace floormat::entities { - -struct inspect_intent_t {}; -struct serialize_intent_t {}; -struct report_intent_t {}; - -template struct entity_accessors; - -} // namespace floormat::entities - namespace floormat::entities::detail { template @@ -55,158 +40,33 @@ template struct decay_tuple_; template struct decay_tuple_> { using type = std::tuple...>; }; template using decay_tuple = typename decay_tuple_::type; -template struct find_reader; - -template struct find_reader { - using type = Default; - static constexpr size_t index = I; -}; - -template -struct find_reader { - using type = typename find_reader::type; - static constexpr size_t index = find_reader::index; -}; - -template -requires FieldReader -struct find_reader { using type = F; static constexpr size_t index = I; }; - } // namespace floormat::entities::detail namespace floormat::entities { -constexpr auto constantly(const auto& x) noexcept { - return [x] (const Ts&...) constexpr -> const auto& { return x; }; -} - -template struct entity_field_base {}; - -template R, FieldWriter W, typename... Ts> -struct entity_field : entity_field_base { -private: - static constexpr auto default_predicate = constantly(field_status::enabled); - static constexpr auto default_c_range = constantly(constraints::range{}); - static constexpr auto default_c_length = constantly(constraints::max_length{size_t(-1)}); - using default_predicate_t = std::decay_t; - using default_c_range_t = std::decay_t; - using default_c_length_t = std::decay_t; - using c_predicate = detail::find_reader; - using c_range = detail::find_reader, default_c_range_t, 0, Ts...>; - using c_length = detail::find_reader; - static constexpr size_t good_arguments = - unsigned(c_predicate::index != sizeof...(Ts)) + - unsigned(c_range::index != sizeof...(Ts)) + - unsigned(c_length::index != sizeof...(Ts)); - static_assert(sizeof...(Ts) == good_arguments, "ignored arguments"); - -public: - using ObjectType = Obj; - using FieldType = Type; - using Reader = R; - using Writer = W; - using Predicate = typename c_predicate::type; - using Range = typename c_range::type; - using Length = typename c_length::type; - - StringView name; - [[fm_no_unique_address]] R reader; - [[fm_no_unique_address]] W writer; - [[fm_no_unique_address]] Predicate predicate; - [[fm_no_unique_address]] Range range; - [[fm_no_unique_address]] Length length; - - fm_DECLARE_DEFAULT_MOVE_COPY_ASSIGNMENTS(entity_field); - - static constexpr decltype(auto) read(const R& reader, const Obj& x) { return detail::read_field::read(x, reader); } - static constexpr void write(const W& writer, Obj& x, Type v); - constexpr decltype(auto) read(const Obj& x) const { return read(reader, x); } - constexpr void write(Obj& x, Type value) const { write(writer, x, move(value)); } - static constexpr bool can_write = !std::is_same_v::writer)>; - - static constexpr field_status is_enabled(const Predicate & p, const Obj& x); - constexpr field_status is_enabled(const Obj& x) const { return is_enabled(predicate, x); } - - static constexpr constraints::range get_range(const Range& r, const Obj& x); - constexpr constraints::range get_range(const Obj& x) const { return get_range(range, x); } - static constexpr constraints::max_length get_max_length(const Length& l, const Obj& x); - constexpr constraints::max_length get_max_length(const Obj& x) const { return get_max_length(length, x); } - - constexpr entity_field(StringView name, R r, W w, Ts&&... ts) noexcept : - name{name}, reader{r}, writer{w}, - predicate { std::get(std::forward_as_tuple(ts..., default_predicate)) }, - range { std::get (std::forward_as_tuple(ts..., default_c_range)) }, - length { std::get (std::forward_as_tuple(ts..., default_c_length)) } - {} - constexpr erased_accessor erased() const; -}; - -template R, FieldWriter W, typename... Ts> -constexpr void entity_field::write(const W& writer, Obj& x, Type v) +template +constexpr void visit_tuple(F&& fun, Tuple&& tuple) { - static_assert(can_write); detail::write_field::write(x, writer, move(v)); + using Size = std::tuple_size>; + if constexpr(Size() > 0) + detail::visit_tuple(floormat::forward(fun), floormat::forward(tuple)); } -template R, FieldWriter W, typename... Ts> -constexpr erased_accessor entity_field::erased() const +template +constexpr bool find_in_tuple(F&& fun, Tuple&& tuple) { - using reader_t = typename erased_accessor::reader_t; - using writer_t = typename erased_accessor::writer_t; - using predicate_t = typename erased_accessor::predicate_t; - using c_range_t = typename erased_accessor::c_range_t; - using c_length_t = typename erased_accessor::c_length_t; - constexpr auto obj_name = name_of, field_name = name_of; - - constexpr auto reader_fn = [](const void* obj, const reader_t* reader, void* value) { - const auto& obj_ = *static_cast(obj); - const auto& reader_ = *static_cast(reader); - auto& value_ = *static_cast(value); - value_ = read(reader_, obj_); - }; - constexpr auto writer_fn = [](void* obj, const writer_t* writer, void* value) { - auto& obj_ = *static_cast(obj); - const auto& writer_ = *static_cast(writer); - Type value_ = move(*static_cast(value)); - write(writer_, obj_, move(value_)); - }; - constexpr auto predicate_fn = [](const void* obj, const predicate_t* predicate) { - const auto& obj_ = *static_cast(obj); - const auto& predicate_ = *static_cast(predicate); - return is_enabled(predicate_, obj_); - }; - constexpr auto writer_stub_fn = [](void*, const writer_t*, void*) { - fm_abort("no writer for this accessor"); - }; - constexpr bool has_writer = !std::is_same_v, std::nullptr_t>; - - constexpr auto c_range_fn = [](const void* obj, const c_range_t* reader) -> erased_constraints::range { - return get_range(*static_cast(reader), *reinterpret_cast(obj)); - }; - constexpr auto c_length_fn = [](const void* obj, const c_length_t* reader) -> erased_constraints::max_length { - return get_max_length(*static_cast(reader), *reinterpret_cast(obj)); - }; - return erased_accessor { - (void*)&reader, has_writer ? (void*)&writer : nullptr, - (void*)&predicate, - (void*)&range, (void*)&length, - name, obj_name, field_name, - reader_fn, has_writer ? writer_fn : writer_stub_fn, - predicate_fn, - c_range_fn, c_length_fn, - }; + using Size = std::tuple_size>; + if constexpr(Size() > 0) + return detail::find_in_tuple(floormat::forward(fun), floormat::forward(tuple)); + else + return false; } -template R, FieldWriter W, typename... Ts> -constexpr field_status entity_field::is_enabled(const Predicate& p, const Obj& x) -{ return detail::read_field::read(x, p); } - -template R, FieldWriter W, typename... Ts> -constexpr constraints::range entity_field::get_range(const Range& r, const Obj& x) -{ return detail::read_field, Range>::read(x, r); } +struct inspect_intent_t {}; +struct serialize_intent_t {}; +struct report_intent_t {}; -template R, FieldWriter W, typename... Ts> -constexpr constraints::max_length entity_field::get_max_length(const Length& l, const Obj& x) -{ return detail::read_field::read(x, l); } +template struct entity_accessors; template struct Entity final { @@ -228,24 +88,6 @@ struct Entity final { }; }; -template -constexpr void visit_tuple(F&& fun, Tuple&& tuple) -{ - using Size = std::tuple_size>; - if constexpr(Size() > 0) - detail::visit_tuple(floormat::forward(fun), floormat::forward(tuple)); -} - -template -constexpr bool find_in_tuple(F&& fun, Tuple&& tuple) -{ - using Size = std::tuple_size>; - if constexpr(Size() > 0) - return detail::find_in_tuple(floormat::forward(fun), floormat::forward(tuple)); - else - return false; -} - constexpr inline auto ignored_write = [](O&, T) {}; } // namespace floormat::entities -- cgit v1.2.3