...
This commit is contained in:
@@ -35,6 +35,8 @@ target_include_directories(
|
|||||||
"$<INSTALL_INTERFACE:include/${PROJECT_NAME}>"
|
"$<INSTALL_INTERFACE:include/${PROJECT_NAME}>"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
target_link_libraries(${PROJECT_NAME} INTERFACE snipplib)
|
||||||
|
|
||||||
if(BUILD_EXAM)
|
if(BUILD_EXAM)
|
||||||
add_executable(device_exam examples/device_exam.cpp)
|
add_executable(device_exam examples/device_exam.cpp)
|
||||||
target_link_libraries(device_exam PRIVATE ${PROJECT_NAME})
|
target_link_libraries(device_exam PRIVATE ${PROJECT_NAME})
|
||||||
|
|||||||
@@ -13,15 +13,30 @@ int main()
|
|||||||
AdcGenericDevice<> dev;
|
AdcGenericDevice<> dev;
|
||||||
|
|
||||||
dev.addAttr(
|
dev.addAttr(
|
||||||
"1", [&i]() { return adc_result_t<int>{i}; },
|
"1", [&i]() -> adc_result_t<int> { return i; },
|
||||||
[&i](int ii) -> adc_error_t {
|
[&i](int ii) -> adc_error_t {
|
||||||
i = ii;
|
i = ii;
|
||||||
return AdcDeviceErrorCode::ERROR_OK;
|
return AdcDeviceErrorCode::ERROR_OK;
|
||||||
});
|
},
|
||||||
|
std::tuple<double, long>{});
|
||||||
|
|
||||||
adc_result_t<int> ri = dev["1"];
|
adc_result_t<int> ri = dev["1"];
|
||||||
if (ri) {
|
if (ri) {
|
||||||
std::println("dev[1] = {}", ri.value());
|
std::println("dev[1] = {}", ri.value());
|
||||||
|
} else {
|
||||||
|
std::println("cannot get dev[1] as int: {}", ri.error().message());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto err = dev["1"] = 77;
|
||||||
|
if (err) {
|
||||||
|
std::println("cannot set dev[1] as int: {}", err.message());
|
||||||
|
}
|
||||||
|
|
||||||
|
adc_result_t<double> rd = dev["1"];
|
||||||
|
if (rd) {
|
||||||
|
std::println("dev[1] = {}", rd.value());
|
||||||
|
} else {
|
||||||
|
std::println("cannot get dev[1] as double: {}", rd.error().message());
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
****************************************************************************************/
|
****************************************************************************************/
|
||||||
|
|
||||||
#include <concepts>
|
#include <concepts>
|
||||||
|
#include <format>
|
||||||
|
#include <functional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
@@ -69,9 +71,9 @@ struct AdcDeviceErrorCategory : std::error_category {
|
|||||||
case AdcDeviceErrorCode::ERROR_OK:
|
case AdcDeviceErrorCode::ERROR_OK:
|
||||||
return "OK";
|
return "OK";
|
||||||
case AdcDeviceErrorCode::ERROR_NO_CMD_ID:
|
case AdcDeviceErrorCode::ERROR_NO_CMD_ID:
|
||||||
return "invalud command ID";
|
return "invalid command ID";
|
||||||
case AdcDeviceErrorCode::ERROR_NO_ATTR_ID:
|
case AdcDeviceErrorCode::ERROR_NO_ATTR_ID:
|
||||||
return "invalud attribute ID";
|
return "invalid attribute ID";
|
||||||
case AdcDeviceErrorCode::ERROR_RO_ATTR:
|
case AdcDeviceErrorCode::ERROR_RO_ATTR:
|
||||||
return "read-only attribute";
|
return "read-only attribute";
|
||||||
case AdcDeviceErrorCode::ERROR_WO_ATTR:
|
case AdcDeviceErrorCode::ERROR_WO_ATTR:
|
||||||
@@ -94,6 +96,11 @@ struct AdcDeviceErrorCategory : std::error_category {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline std::error_code make_error_code(AdcDeviceErrorCode ec)
|
||||||
|
{
|
||||||
|
return std::error_code(static_cast<int>(ec), AdcDeviceErrorCategory::get());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template <std::formattable<char> ATTR_ID_T = std::string_view, std::formattable<char> CMD_ID_T = std::string_view>
|
template <std::formattable<char> ATTR_ID_T = std::string_view, std::formattable<char> CMD_ID_T = std::string_view>
|
||||||
class AdcGenericDevice
|
class AdcGenericDevice
|
||||||
@@ -150,13 +157,13 @@ protected:
|
|||||||
template <typename VT>
|
template <typename VT>
|
||||||
operator adc_result_t<VT>()
|
operator adc_result_t<VT>()
|
||||||
{
|
{
|
||||||
auto v = _dev._attrs.template get<VT>(_id);
|
auto const& attr = _dev._attrs.template get<attr_t<VT>>(_id);
|
||||||
if (v) {
|
if (attr) {
|
||||||
return v.value();
|
return attr.value().getter();
|
||||||
}
|
}
|
||||||
|
|
||||||
// error
|
// error
|
||||||
if (v.error() == snplib::HeterogenMap<ATTR_ID_T>::ERROR_NO_ELEM) {
|
if (attr.error() == snplib::HeterogenMap<ATTR_ID_T>::ERROR_NO_ELEM) {
|
||||||
return std::unexpected(AdcDeviceErrorCode::ERROR_NO_ATTR_ID);
|
return std::unexpected(AdcDeviceErrorCode::ERROR_NO_ATTR_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,10 +173,12 @@ protected:
|
|||||||
template <typename VT>
|
template <typename VT>
|
||||||
adc_error_t operator=(VT&& val)
|
adc_error_t operator=(VT&& val)
|
||||||
{
|
{
|
||||||
auto err = _dev._attrs.set(_id, std::forward<VT>(val));
|
auto const& attr = _dev._attrs.template get<attr_t<VT>>(_id);
|
||||||
if (err == snplib::HeterogenMap<ATTR_ID_T>::ERROR_OK) {
|
if (attr) {
|
||||||
return AdcDeviceErrorCode::ERROR_OK;
|
return attr.value().setter(std::forward<VT>(val));
|
||||||
} else if (err == snplib::HeterogenMap<ATTR_ID_T>::ERROR_NO_ELEM) {
|
}
|
||||||
|
|
||||||
|
if (attr.error() == snplib::HeterogenMap<ATTR_ID_T>::ERROR_NO_ELEM) {
|
||||||
return AdcDeviceErrorCode::ERROR_NO_ATTR_ID;
|
return AdcDeviceErrorCode::ERROR_NO_ATTR_ID;
|
||||||
} else {
|
} else {
|
||||||
return AdcDeviceErrorCode::ERROR_UNKNOWN;
|
return AdcDeviceErrorCode::ERROR_UNKNOWN;
|
||||||
@@ -196,8 +205,8 @@ public:
|
|||||||
_commands.emplace(std::move(id), std::forward<ET>(exec_func));
|
_commands.emplace(std::move(id), std::forward<ET>(exec_func));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename GT, typename ST>
|
template <typename GT, typename ST, typename... VTs>
|
||||||
void addAttr(ATTR_ID_T id, GT&& getter, ST&& setter)
|
void addAttr(ATTR_ID_T id, GT&& getter, ST&& setter, std::tuple<VTs...> = std::tuple())
|
||||||
{
|
{
|
||||||
// deduce attribute value type
|
// deduce attribute value type
|
||||||
using ret_t = std::invoke_result_t<GT>;
|
using ret_t = std::invoke_result_t<GT>;
|
||||||
@@ -210,6 +219,19 @@ public:
|
|||||||
"Invalid return type of the setter!");
|
"Invalid return type of the setter!");
|
||||||
|
|
||||||
_attrs.push(std::move(id), attr_t<v_t>{.getter = std::forward<GT>(getter), .setter = std::forward<ST>(setter)});
|
_attrs.push(std::move(id), attr_t<v_t>{.getter = std::forward<GT>(getter), .setter = std::forward<ST>(setter)});
|
||||||
|
|
||||||
|
// if constexpr (sizeof...(VTs)) {
|
||||||
|
// auto func = [id, this]<size_t I>() {
|
||||||
|
// using u_t = std::tuple_element_t<I, std::tuple<VTs...>>;
|
||||||
|
// if constexpr (!requires(u_t u, v_t v) {
|
||||||
|
// u = v;
|
||||||
|
// v = u;
|
||||||
|
// }) {
|
||||||
|
// static_assert(false, "Invalid user type!");
|
||||||
|
// }
|
||||||
|
// _attrs.push(std::move(id), attr_t<u_t>{.getter = []() {}, .setter = []() {}});
|
||||||
|
// };
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
adc_error_t operator()(CMD_ID_T id)
|
adc_error_t operator()(CMD_ID_T id)
|
||||||
|
|||||||
Reference in New Issue
Block a user