mountcontrol/cxx/mcc_fsm.h
Timur A. Fatkhullin 156dfb13ba FSM ...
2025-05-27 23:40:43 +03:00

244 lines
6.5 KiB
C++

#pragma once
/* MOUNT CONTROL COMPONENTS LIBRARY */
/* FINITE-STATE MACHINE IMPLEMENTATION */
#include <limits>
#include <tuple>
#include <type_traits>
#include <utility>
namespace mcc
{
namespace traits
{
template <typename T>
concept std_pair_c = requires(T t) {
[]<typename T1, typename T2>(std::type_identity<std::pair<T1, T2>>) {
}(std::type_identity<std::remove_cvref_t<T>>());
};
} // namespace traits
namespace fsm
{
/* A TYPE TO HOLD COMPILE-TIME SEQUENCE OF std::pair */
template <traits::std_pair_c... pairs>
struct pair_holder_t;
template <traits::std_pair_c head, traits::std_pair_c... tail>
struct pair_holder_t<head, tail...> {
// using self_t = pair_holder_t<head, tail...>;
// using self_data_t = std::tuple<head, tail...>;
typedef pair_holder_t<head, tail...> self_t;
typedef std::tuple<head, tail...> sequence_t;
};
template <>
struct pair_holder_t<> {
// using self_data_t = std::tuple<>;
typedef std::tuple<> sequence_t;
constexpr static bool valid = true;
};
} // namespace fsm
namespace traits
{
template <typename T>
concept pair_holder_c = requires {
[]<mcc::traits::std_pair_c... Ts>(std::type_identity<fsm::pair_holder_t<Ts...>>) {
//
}(std::type_identity<std::remove_cvref_t<T>>());
};
} // namespace traits
namespace fsm
{
/* A CLASS TO FIND TYPE OF pair.second ELEMENT BY ITS pair.first one IN PAIR-SEQUENCE */
template <typename FirstT, traits::pair_holder_c PHLDT>
struct pair_holder_find_t;
template <typename FirstT, typename CurrentFirstT, typename SecondT, mcc::traits::std_pair_c... tail>
struct pair_holder_find_t<FirstT, pair_holder_t<std::pair<CurrentFirstT, SecondT>, tail...>>
: pair_holder_find_t<FirstT, pair_holder_t<tail...>> {
};
template <typename FirstT>
struct pair_holder_find_t<FirstT, pair_holder_t<>> {
typedef std::nullptr_t result_t;
};
template <typename FirstT, typename SecondT, mcc::traits::std_pair_c... tail>
struct pair_holder_find_t<FirstT, pair_holder_t<std::pair<FirstT, SecondT>, tail...>> {
typedef SecondT result_t;
};
/* A CLASS TO GET ALL pair.first TYPES IN PAIR-SEQUENCE */
template <traits::pair_holder_c PHLDT>
struct pair_holder_first_t;
template <typename FirstT, typename SecondT, mcc::traits::std_pair_c... tail>
struct pair_holder_first_t<pair_holder_t<std::pair<FirstT, SecondT>, tail...>> {
typedef decltype(std::tuple_cat(
std::declval<std::tuple<FirstT>>(),
std::declval<typename pair_holder_first_t<pair_holder_t<tail...>>::first_t>())) first_t;
};
template <>
struct pair_holder_first_t<pair_holder_t<>> {
typedef std::tuple<> first_t;
};
/* A CLASS TO GET ALL pair.second TYPES IN PAIR-SEQUENCE */
template <traits::pair_holder_c PHLDT>
struct pair_holder_second_t;
template <typename FirstT, typename SecondT, mcc::traits::std_pair_c... tail>
struct pair_holder_second_t<pair_holder_t<std::pair<FirstT, SecondT>, tail...>> {
typedef decltype(std::tuple_cat(
std::declval<std::tuple<SecondT>>(),
std::declval<typename pair_holder_second_t<pair_holder_t<tail...>>::second_t>())) second_t;
};
template <>
struct pair_holder_second_t<pair_holder_t<>> {
typedef std::tuple<> second_t;
};
/* A TYPE TO IMPLEMENT TUPLE OF UNIQUE TYPES */
template <typename... TYPEs>
class unique_tuple_t
{
template <typename IT, typename UniqTupleT>
struct in_tuple : in_tuple<IT, typename UniqTupleT::tuple_t> {
};
template <typename IT, typename... Ts>
struct in_tuple<IT, std::tuple<Ts...>> : std::disjunction<std::is_same<IT, Ts>...> {
};
// insert
template <typename IT, typename UniqTupleT, bool = in_tuple<IT, UniqTupleT>::value>
struct insert;
template <typename IT, typename... Ts>
struct insert<IT, std::tuple<Ts...>, false> {
typedef std::tuple<IT, Ts...> tuple_t;
typedef std::tuple<> non_unique_t;
};
template <typename IT, typename... Ts>
struct insert<IT, std::tuple<Ts...>, true> {
typedef std::tuple<Ts...> tuple_t;
typedef std::tuple<IT> non_unique_t;
};
// merge
template <typename ITupleT, typename OTupleT>
struct merge;
template <typename MT, typename... MTs, typename... OTs>
struct merge<std::tuple<MT, MTs...>, std::tuple<OTs...>> {
typedef merge<std::tuple<MTs...>, std::tuple<OTs...>> tail_t;
typedef insert<MT, typename tail_t::tuple_t> curr_tuple_t;
typedef typename curr_tuple_t::tuple_t tuple_t;
typedef decltype(std::tuple_cat(std::declval<typename curr_tuple_t::non_unique_t>(),
std::declval<typename tail_t::non_unique_t>())) non_unique_t;
};
template <typename... MTs>
struct merge<std::tuple<>, std::tuple<MTs...>> {
typedef std::tuple<MTs...> tuple_t;
typedef std::tuple<> non_unique_t;
};
public:
typedef typename merge<std::tuple<TYPEs...>, std::tuple<>>::tuple_t tuple_t;
typedef typename merge<std::tuple<TYPEs...>, std::tuple<>>::non_unique_t non_unique_t;
};
} // namespace fsm
namespace traits
{
template <typename T>
concept unique_tuple_c = requires {
[]<typename... Ts>(std::type_identity<fsm::unique_tuple_t<Ts...>>) {}(std::type_identity<std::remove_cvref_t<T>>());
};
} // namespace traits
namespace fsm
{
// GET INDEX OF GIVEN TYPE IN UNIQUE TUPLE
namespace details
{
// template <typename T, mcc::traits::unique_tuple_c UT, std::size_t I = 0>
template <typename T, typename TupleT, std::size_t I = 0>
struct unique_tuple_type_index_helper_t;
template <typename T, typename HeadT, typename... TailT, std::size_t I>
struct unique_tuple_type_index_helper_t<T, std::tuple<HeadT, TailT...>, I> {
constexpr static std::size_t index = unique_tuple_type_index_helper_t<T, std::tuple<TailT...>, I + 1>::index;
};
template <typename T, typename... TailT, std::size_t I>
struct unique_tuple_type_index_helper_t<T, std::tuple<T, TailT...>, I> {
constexpr static std::size_t index = I;
};
template <typename T, std::size_t I>
struct unique_tuple_type_index_helper_t<T, std::tuple<>, I> {
constexpr static std::size_t index = std::numeric_limits<std::size_t>::max();
static_assert(false, "INVALID INPUT TYPE!");
};
} // namespace details
template <typename T, mcc::traits::unique_tuple_c UT>
struct unique_tuple_type_index_t : details::unique_tuple_type_index_helper_t<T, typename UT::tuple_t, 0> {
};
template <typename T, mcc::traits::unique_tuple_c UT>
constexpr static std::size_t unique_tuple_type_index_v = unique_tuple_type_index_t<T, typename UT::tuple_t>::index;
} // namespace fsm
} // namespace mcc