diff --git a/cxx/CMakeLists.txt b/cxx/CMakeLists.txt index 241d8eb..162326a 100644 --- a/cxx/CMakeLists.txt +++ b/cxx/CMakeLists.txt @@ -125,7 +125,8 @@ add_library(${CNTR_PROTO_LIB} STATIC ${CNTR_PROTO_LIB_SRC}) set(MOUNT_SERVER_APP_SRC mount.h mount_state.h mount_server.cpp comm_server.h comm_server_endpoint.h comm_server_configfile.h mount_astrom.h mount_astrom_default.h mcc_coord.h mount_pz.h) set(MOUNT_SERVER_APP mount_server) -add_executable(${MOUNT_SERVER_APP} ${MOUNT_SERVER_APP_SRC}) +add_executable(${MOUNT_SERVER_APP} ${MOUNT_SERVER_APP_SRC} + mcc_fsm.h) # target_include_directories(${MOUNT_SERVER_APP} PUBLIC ${ERFA_INCLUDE_DIR}) target_link_libraries(${MOUNT_SERVER_APP} ${CNTR_PROTO_LIB} spdlog::spdlog_header_only ERFA_LIB) @@ -147,5 +148,9 @@ if (WITH_TESTS) add_executable(${FITPACK_TEST_APP} tests/fitpack_test.cpp) target_link_libraries(${FITPACK_TEST_APP} fitpack) target_include_directories(${FITPACK_TEST_APP} PRIVATE ${FITPACK_INCLUDE_DIR}) - message(STATUS "INC UP: " ${FITPACK_INCLUDE_DIR}) + # message(STATUS "INC UP: " ${FITPACK_INCLUDE_DIR}) + + set(FSM_TEST_APP fsm_test) + add_executable(${FSM_TEST_APP} tests/fsm_test.cpp) + endif() diff --git a/cxx/mcc_fsm.h b/cxx/mcc_fsm.h new file mode 100644 index 0000000..6db743e --- /dev/null +++ b/cxx/mcc_fsm.h @@ -0,0 +1,243 @@ +#pragma once + + +/* MOUNT CONTROL COMPONENTS LIBRARY */ + +/* FINITE-STATE MACHINE IMPLEMENTATION */ + + +#include +#include +#include +#include + +namespace mcc +{ + +namespace traits +{ + +template +concept std_pair_c = requires(T t) { + [](std::type_identity>) { + + }(std::type_identity>()); +}; + + +} // namespace traits + + +namespace fsm +{ + +/* A TYPE TO HOLD COMPILE-TIME SEQUENCE OF std::pair */ +template +struct pair_holder_t; + +template +struct pair_holder_t { + // using self_t = pair_holder_t; + // using self_data_t = std::tuple; + typedef pair_holder_t self_t; + typedef std::tuple 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 +concept pair_holder_c = requires { + [](std::type_identity>) { + // + }(std::type_identity>()); +}; + +} // namespace traits + + +namespace fsm +{ + +/* A CLASS TO FIND TYPE OF pair.second ELEMENT BY ITS pair.first one IN PAIR-SEQUENCE */ + +template +struct pair_holder_find_t; + +template +struct pair_holder_find_t, tail...>> + : pair_holder_find_t> { +}; + +template +struct pair_holder_find_t> { + typedef std::nullptr_t result_t; +}; + +template +struct pair_holder_find_t, tail...>> { + typedef SecondT result_t; +}; + + + +/* A CLASS TO GET ALL pair.first TYPES IN PAIR-SEQUENCE */ + +template +struct pair_holder_first_t; + +template +struct pair_holder_first_t, tail...>> { + typedef decltype(std::tuple_cat( + std::declval>(), + std::declval>::first_t>())) first_t; +}; + + +template <> +struct pair_holder_first_t> { + typedef std::tuple<> first_t; +}; + + +/* A CLASS TO GET ALL pair.second TYPES IN PAIR-SEQUENCE */ + +template +struct pair_holder_second_t; + +template +struct pair_holder_second_t, tail...>> { + typedef decltype(std::tuple_cat( + std::declval>(), + std::declval>::second_t>())) second_t; +}; + + +template <> +struct pair_holder_second_t> { + typedef std::tuple<> second_t; +}; + + + +/* A TYPE TO IMPLEMENT TUPLE OF UNIQUE TYPES */ + +template +class unique_tuple_t +{ + template + struct in_tuple : in_tuple { + }; + + template + struct in_tuple> : std::disjunction...> { + }; + + // insert + template ::value> + struct insert; + + template + struct insert, false> { + typedef std::tuple tuple_t; + typedef std::tuple<> non_unique_t; + }; + + template + struct insert, true> { + typedef std::tuple tuple_t; + typedef std::tuple non_unique_t; + }; + + + // merge + template + struct merge; + + template + struct merge, std::tuple> { + typedef merge, std::tuple> tail_t; + typedef insert curr_tuple_t; + + typedef typename curr_tuple_t::tuple_t tuple_t; + typedef decltype(std::tuple_cat(std::declval(), + std::declval())) non_unique_t; + }; + + template + struct merge, std::tuple> { + typedef std::tuple tuple_t; + typedef std::tuple<> non_unique_t; + }; + +public: + typedef typename merge, std::tuple<>>::tuple_t tuple_t; + typedef typename merge, std::tuple<>>::non_unique_t non_unique_t; +}; + +} // namespace fsm + + +namespace traits +{ + +template +concept unique_tuple_c = requires { + [](std::type_identity>) {}(std::type_identity>()); +}; + +} // namespace traits + + +namespace fsm +{ + +// GET INDEX OF GIVEN TYPE IN UNIQUE TUPLE +namespace details +{ + +// template +template +struct unique_tuple_type_index_helper_t; + + +template +struct unique_tuple_type_index_helper_t, I> { + constexpr static std::size_t index = unique_tuple_type_index_helper_t, I + 1>::index; +}; + + +template +struct unique_tuple_type_index_helper_t, I> { + constexpr static std::size_t index = I; +}; + +template +struct unique_tuple_type_index_helper_t, I> { + constexpr static std::size_t index = std::numeric_limits::max(); + static_assert(false, "INVALID INPUT TYPE!"); +}; + +} // namespace details + + +template +struct unique_tuple_type_index_t : details::unique_tuple_type_index_helper_t { +}; + +template +constexpr static std::size_t unique_tuple_type_index_v = unique_tuple_type_index_t::index; + +} // namespace fsm + + +} // namespace mcc diff --git a/cxx/mount.h b/cxx/mount.h index 5e0b30b..2102c65 100644 --- a/cxx/mount.h +++ b/cxx/mount.h @@ -278,7 +278,7 @@ public: virtual ~MccMountState() { - _mount.logTrace("Delete MccMountState instance: {}", (void)this); + _mount.logTrace("Delete MccMountState instance: {}", (void*)this); }; diff --git a/cxx/tests/fsm_test.cpp b/cxx/tests/fsm_test.cpp new file mode 100644 index 0000000..f9b9fec --- /dev/null +++ b/cxx/tests/fsm_test.cpp @@ -0,0 +1,41 @@ +#include +#include + +#include "../mcc_fsm.h" + +struct S { +}; + +int main() +{ + using namespace mcc; + + typedef fsm::unique_tuple_t ut_t; + + std::cout << "type index: " << fsm::unique_tuple_type_index_t::index << " (double)\n"; + std::cout << "type index: " << fsm::unique_tuple_type_index_t::index << " (int)\n"; + std::cout << "type index: " << fsm::unique_tuple_type_index_t::index << " (long)\n"; + // std::cout << "type index: " << fsm::unique_tuple_type_index_t::index << " (struct S)\n"; + + std::cout << typeid(ut_t::tuple_t).name() << "\n"; + std::cout << typeid(ut_t::non_unique_t).name() << "\n"; + + + typedef fsm::pair_holder_t, std::pair, std::pair> ph_t; + + // using s_t = fsm::pair_holder_find_t::result_t; + using s_t = fsm::pair_holder_find_t::result_t; + if constexpr (std::is_null_pointer_v) { + std::cout << "second type: invalid input type!\n"; + } else { + std::cout << "second type: " << typeid(s_t).name() << "\n"; + } + + using t1_t = fsm::pair_holder_first_t::first_t; + std::cout << "first types: " << typeid(t1_t).name() << "\n"; + + using t2_t = fsm::pair_holder_second_t::second_t; + std::cout << "second types: " << typeid(t2_t).name() << "\n"; + + return 0; +}