...
This commit is contained in:
parent
75ec7065d2
commit
d9c87aed1f
@ -5,14 +5,21 @@ project(ADC LANGUAGES CXX)
|
|||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
|
||||||
|
set(ADC_COMMON_HEADERS
|
||||||
|
common/adc_value_holder.h
|
||||||
|
)
|
||||||
|
|
||||||
set(ADC_DEVICE_HEADERS
|
set(ADC_DEVICE_HEADERS
|
||||||
device/adc_value_holder.h
|
device/adc_device_attribute.h
|
||||||
|
device/adc_device_command.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
add_library(${PROJECT_NAME} INTERFACE ${ADC_DEVICE_HEADERS})
|
add_library(${PROJECT_NAME} INTERFACE ${ADC_COMMON_HEADERS} ${ADC_DEVICE_HEADERS}
|
||||||
|
common/adc_traits.h)
|
||||||
target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_20)
|
target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_20)
|
||||||
# target_link_libraries(${PROJECT_NAME} INTERFACE ASIO::ASIO)
|
# target_link_libraries(${PROJECT_NAME} INTERFACE ASIO::ASIO)
|
||||||
target_include_directories(
|
target_include_directories(
|
||||||
|
|||||||
83
common/adc_traits.h
Normal file
83
common/adc_traits.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <tuple>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
ABSTRACT DEVICE COMPONENTS LIBRARY
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
namespace adc::traits
|
||||||
|
{
|
||||||
|
|
||||||
|
// deduce returned type of callable
|
||||||
|
template <typename T>
|
||||||
|
using adc_retval_t = std::invoke_result_t<std::remove_cvref_t<T>>;
|
||||||
|
|
||||||
|
|
||||||
|
// helper classes
|
||||||
|
template <typename... Ts>
|
||||||
|
struct adc_func_traits_helper_t;
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
struct adc_func_traits_helper_t<R> {
|
||||||
|
using ret_t = R;
|
||||||
|
using args_t = std::tuple<>;
|
||||||
|
using arg1_t = void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename Arg, typename... Args>
|
||||||
|
struct adc_func_traits_helper_t<R, Arg, Args...> {
|
||||||
|
using ret_t = R;
|
||||||
|
using args_t = std::tuple<Arg, Args...>;
|
||||||
|
using arg1_t = Arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// callable traits
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
struct adc_func_traits;
|
||||||
|
|
||||||
|
template <typename R, typename... Args>
|
||||||
|
struct adc_func_traits<R (*)(Args...)> : adc_func_traits_helper_t<R, Args...> {
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename... Args>
|
||||||
|
struct adc_func_traits<R(Args...)> : adc_func_traits_helper_t<R, Args...> {
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename C, typename R, typename... Args>
|
||||||
|
struct adc_func_traits<R (C::*)(Args...)> : adc_func_traits_helper_t<R, Args...> {
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename C, typename R, typename... Args>
|
||||||
|
struct adc_func_traits<R (C::*)(Args...) const> : adc_func_traits_helper_t<R, Args...> {
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
struct adc_func_traits : adc_func_traits<decltype(&F::operator())> {
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// deduce type
|
||||||
|
template <typename T>
|
||||||
|
using adc_deduced_type =
|
||||||
|
std::conditional_t<std::is_lvalue_reference_v<T> && !std::is_const_v<std::remove_reference_t<T>>,
|
||||||
|
T,
|
||||||
|
std::remove_cvref_t<T>>;
|
||||||
|
|
||||||
|
|
||||||
|
// perfect-forwarding wrapper
|
||||||
|
template <typename T, typename... Ts>
|
||||||
|
auto adc_pf_wrapper(T&& v, Ts&&... vs)
|
||||||
|
{
|
||||||
|
return std::tuple<adc_deduced_type<T>, adc_deduced_type<Ts>...>(std::forward<T>(v), std::forward<Ts>(vs)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace adc::traits
|
||||||
@ -11,11 +11,11 @@
|
|||||||
#include <concepts>
|
#include <concepts>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <ranges>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
#include <tuple>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <typeindex>
|
#include <typeindex>
|
||||||
|
|
||||||
|
#include "adc_traits.h"
|
||||||
|
|
||||||
namespace adc
|
namespace adc
|
||||||
{
|
{
|
||||||
@ -46,70 +46,6 @@ namespace adc
|
|||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
namespace traits
|
|
||||||
{
|
|
||||||
|
|
||||||
// deduce returned type of callable
|
|
||||||
template <typename T>
|
|
||||||
using adc_retval_t = std::invoke_result_t<std::remove_cvref_t<T>>;
|
|
||||||
|
|
||||||
|
|
||||||
// helper classes
|
|
||||||
template <typename... Ts>
|
|
||||||
struct adc_func_traits_helper_t;
|
|
||||||
|
|
||||||
template <typename R>
|
|
||||||
struct adc_func_traits_helper_t<R> {
|
|
||||||
using ret_t = R;
|
|
||||||
using args_t = std::tuple<>;
|
|
||||||
using arg1_t = void;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename R, typename Arg, typename... Args>
|
|
||||||
struct adc_func_traits_helper_t<R, Arg, Args...> {
|
|
||||||
using ret_t = R;
|
|
||||||
using args_t = std::tuple<Arg, Args...>;
|
|
||||||
using arg1_t = Arg;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// callable traits
|
|
||||||
|
|
||||||
template <typename F>
|
|
||||||
struct adc_func_traits;
|
|
||||||
|
|
||||||
template <typename R, typename... Args>
|
|
||||||
struct adc_func_traits<R (*)(Args...)> : adc_func_traits_helper_t<R, Args...> {
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename R, typename... Args>
|
|
||||||
struct adc_func_traits<R(Args...)> : adc_func_traits_helper_t<R, Args...> {
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename C, typename R, typename... Args>
|
|
||||||
struct adc_func_traits<R (C::*)(Args...)> : adc_func_traits_helper_t<R, Args...> {
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename C, typename R, typename... Args>
|
|
||||||
struct adc_func_traits<R (C::*)(Args...) const> : adc_func_traits_helper_t<R, Args...> {
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename F>
|
|
||||||
struct adc_func_traits : adc_func_traits<decltype(&F::operator())> {
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// deduce type
|
|
||||||
template <typename T>
|
|
||||||
using adc_deduced_type =
|
|
||||||
std::conditional_t<std::is_lvalue_reference_v<T> && !std::is_const_v<std::remove_reference_t<T>>,
|
|
||||||
T,
|
|
||||||
std::remove_cvref_t<T>>;
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace traits
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// error category
|
// error category
|
||||||
struct AdcValueHolderErrorCategory : public std::error_category {
|
struct AdcValueHolderErrorCategory : public std::error_category {
|
||||||
@ -161,7 +97,7 @@ class AdcValueHolder
|
|||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using arg_t = typename traits::adc_func_traits<T>::arg1_t;
|
using arg_t = typename traits::adc_func_traits<T>::ret_t;
|
||||||
|
|
||||||
std::function<void(std::any&)> _getterWrapper;
|
std::function<void(std::any&)> _getterWrapper;
|
||||||
std::function<void(const std::any&)> _setterWrapper;
|
std::function<void(const std::any&)> _setterWrapper;
|
||||||
@ -189,8 +125,7 @@ public:
|
|||||||
static_assert(std::is_same_v<value_t, void>, "THE getter MUST NOT RETURN void type!!!");
|
static_assert(std::is_same_v<value_t, void>, "THE getter MUST NOT RETURN void type!!!");
|
||||||
|
|
||||||
using g_t = decltype(getter);
|
using g_t = decltype(getter);
|
||||||
_getterWrapper = [wrapper =
|
_getterWrapper = [wrapper = traits::adc_pf_wrapper(std::forward<g_t>(getter))](std::any& val) {
|
||||||
std::tuple<traits::adc_deduced_type<g_t>>(std::forward<g_t>(getter))](std::any& val) {
|
|
||||||
auto& getter = std::get<0>(wrapper);
|
auto& getter = std::get<0>(wrapper);
|
||||||
val = getter();
|
val = getter();
|
||||||
};
|
};
|
||||||
@ -199,16 +134,15 @@ public:
|
|||||||
using vld_t = decltype(validator);
|
using vld_t = decltype(validator);
|
||||||
using s_t = decltype(setter);
|
using s_t = decltype(setter);
|
||||||
|
|
||||||
if constexpr (std::is_same_v<vld_t, decltype(AdcValueHolderDummyValidator)>) {
|
if constexpr (std::is_same_v<vld_t, decltype(AdcValueHolderDummyValidator)>) { // no validation
|
||||||
_setterWrapper = [wrapper = std::tuple<traits::adc_deduced_type<s_t>>(std::forward<s_t>(setter)),
|
_setterWrapper = [wrapper = traits::adc_pf_wrapper(std::forward<s_t>(setter)), this](const std::any& val) {
|
||||||
this](const std::any& val) {
|
|
||||||
auto& setter = std::get<0>(wrapper);
|
auto& setter = std::get<0>(wrapper);
|
||||||
|
|
||||||
setter(std::any_cast<value_t>(val));
|
setter(std::any_cast<value_t>(val));
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
_setterWrapper = [wrapper = std::tuple<traits::adc_deduced_type<s_t>, traits::adc_deduced_type<vld_t>>(
|
_setterWrapper = [wrapper =
|
||||||
std::forward<s_t>(setter), std::forward<vld_t>(validator)),
|
traits::adc_pf_wrapper(std::forward<s_t>(setter), std::forward<vld_t>(validator)),
|
||||||
this](const std::any& val) {
|
this](const std::any& val) {
|
||||||
auto& setter = std::get<0>(wrapper);
|
auto& setter = std::get<0>(wrapper);
|
||||||
auto& validator = std::get<1>(wrapper);
|
auto& validator = std::get<1>(wrapper);
|
||||||
@ -239,6 +173,17 @@ public:
|
|||||||
|
|
||||||
/* PUBLIC METHODS */
|
/* PUBLIC METHODS */
|
||||||
|
|
||||||
|
|
||||||
|
std::type_index valueTypeIndex() const { return _internalTypeIndex; }
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<std::type_index> convTypeIndices()
|
||||||
|
{
|
||||||
|
auto kv = std::views::keys(_convertFromInternal);
|
||||||
|
return {kv.begin(), kv.end()};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename UT>
|
template <typename UT>
|
||||||
AdcValueHolder& addConvertFunc(std::invocable<std::any&> auto&& func_to_internal,
|
AdcValueHolder& addConvertFunc(std::invocable<std::any&> auto&& func_to_internal,
|
||||||
std::invocable<std::any&> auto&& func_from_internal)
|
std::invocable<std::any&> auto&& func_from_internal)
|
||||||
1
device/adc_device_attribute.h
Normal file
1
device/adc_device_attribute.h
Normal file
@ -0,0 +1 @@
|
|||||||
|
#pragma once
|
||||||
117
device/adc_device_command.h
Normal file
117
device/adc_device_command.h
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
ABSTRACT DEVICE COMPONENTS LIBRARY
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include "../common/adc_value_holder.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace adc
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename IdentT, typename SerializedT = std::string>
|
||||||
|
class AdcDeviceCommand
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
IdentT _ident;
|
||||||
|
|
||||||
|
std::unique_ptr<AdcValueHolder> _commandArgUptr;
|
||||||
|
|
||||||
|
std::function<void()> _execFuncWrapper;
|
||||||
|
std::function<void(std::any&)> _deserializerWrapper;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef IdentT ident_t;
|
||||||
|
typedef SerializedT serialized_t;
|
||||||
|
|
||||||
|
|
||||||
|
template <typename ExecFuncT,
|
||||||
|
typename DeserializerT,
|
||||||
|
typename ValidatorT = decltype(AdcValueHolder::AdcValueHolderDummyValidator)>
|
||||||
|
AdcDeviceCommand(const IdentT& ident,
|
||||||
|
ExecFuncT&& exec_func,
|
||||||
|
DeserializerT&& deserializer,
|
||||||
|
ValidatorT&& validator = AdcValueHolder::AdcValueHolderDummyValidator)
|
||||||
|
: _ident(ident), _commandArgUptr()
|
||||||
|
{
|
||||||
|
using sign_t = traits::adc_func_traits<ExecFuncT>;
|
||||||
|
|
||||||
|
static_assert(std::tuple_size_v<typename sign_t::args_t> > 1,
|
||||||
|
"COMMAND EXECUTION FUNCTION MUST ACCEPT 0 OR EXACTLY 1 ARGUMENT!!!");
|
||||||
|
|
||||||
|
if constexpr (std::tuple_size_v<typename sign_t::args_t>) { // command with argument
|
||||||
|
using value_t = typename sign_t::arg1_t;
|
||||||
|
|
||||||
|
static_assert(std::predicate<ValidatorT, const value_t&>, "INVALID TYPE OF VALIDATOR");
|
||||||
|
|
||||||
|
static_assert(std::invocable<DeserializerT, const SerializedT&>, "INVALID TYPE OF DESERIALIZER");
|
||||||
|
static_assert(std::is_convertible_v<std::invoke_result_t<DeserializerT, const SerializedT&>, value_t>,
|
||||||
|
"INVALID RETURN TYPE OF DESERIALIZER");
|
||||||
|
|
||||||
|
|
||||||
|
auto command_arg = std::shared_ptr<value_t>(value_t());
|
||||||
|
|
||||||
|
_commandArgUptr = std::make_unique<AdcValueHolder>(
|
||||||
|
[command_arg]() { return *command_arg; }, [command_arg](const value_t& value) { *command_arg = value; },
|
||||||
|
std::forward<ValidatorT>(validator));
|
||||||
|
|
||||||
|
_execFuncWrapper = [wrapper = traits::adc_pf_wrapper(std::forward<ExecFuncT>(exec_func)), this]() {
|
||||||
|
auto& exec_func = std::get<0>(wrapper);
|
||||||
|
value_t val = *_commandArgUptr;
|
||||||
|
exec_func(val);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
_deserializerWrapper =
|
||||||
|
[wrapper = traits::adc_pf_wrapper(std::forward<DeserializerT>(deserializer))](std::any& val) {
|
||||||
|
auto& deserializer = std::get<0>(wrapper);
|
||||||
|
val = std::make_any<value_t>(deserializer(std::any_cast<SerializedT>(val)));
|
||||||
|
};
|
||||||
|
|
||||||
|
// setup only convert-to-native-value function (deserializer)
|
||||||
|
_commandArgUptr->addConvertFunc<SerializedT>(std::forward<DeserializerT>(deserializer), []() {});
|
||||||
|
} else { // command without argument (ignore deserializer and validator)
|
||||||
|
_execFuncWrapper = std::forward<ExecFuncT>(exec_func);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual ~AdcDeviceCommand() = default;
|
||||||
|
|
||||||
|
|
||||||
|
/* PUBLIC METHODS */
|
||||||
|
|
||||||
|
IdentT ident() const { return ident; }
|
||||||
|
|
||||||
|
|
||||||
|
template <typename ValueT>
|
||||||
|
void operator()(const ValueT& value)
|
||||||
|
{
|
||||||
|
if (_commandArgUptr) { // command with argument
|
||||||
|
*_commandArgUptr = value;
|
||||||
|
}
|
||||||
|
_execFuncWrapper();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void operator()()
|
||||||
|
{
|
||||||
|
if (_commandArgUptr) { // command with argument
|
||||||
|
throw 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
_execFuncWrapper();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace adc
|
||||||
Loading…
x
Reference in New Issue
Block a user