Compare commits
14 Commits
4c500c0308
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| c6ee8f6c5b | |||
| 4491f27c68 | |||
| 60dbba7a5f | |||
|
|
176022d490 | ||
| 13b22b0d1c | |||
| b90a59c3ed | |||
| 201537e324 | |||
| e1f7070589 | |||
| fd21fbfe1d | |||
| 49734de1c4 | |||
| 433f38b5a7 | |||
| bdaaaab559 | |||
| 6e1ef26aa6 | |||
| eaa8a366b2 |
@@ -45,6 +45,11 @@ if(ADCLIB_BUILD_EXAM)
|
|||||||
target_link_libraries(device_exam PRIVATE ${PROJECT_NAME})
|
target_link_libraries(device_exam PRIVATE ${PROJECT_NAME})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(ADCLIB_BUILD_EXAM)
|
||||||
|
add_executable(netmsg_exam examples/netmsg_exam.cpp)
|
||||||
|
target_link_libraries(netmsg_exam PRIVATE ${PROJECT_NAME})
|
||||||
|
endif()
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
install(
|
install(
|
||||||
TARGETS ${PROJECT_NAME}
|
TARGETS ${PROJECT_NAME}
|
||||||
|
|||||||
@@ -6,51 +6,112 @@ using namespace adc;
|
|||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
std::string id1 = "1", id2 = "2", id3 = "str";
|
||||||
|
|
||||||
int i = 10;
|
int i = 10;
|
||||||
double d = 8.1;
|
double d = 8.1;
|
||||||
std::string s{"dwedjkwlk"};
|
std::string s{"dwedjkwlk"};
|
||||||
|
|
||||||
AdcGenericDevice<> dev("DEV#1");
|
AdcGenericDevice<> dev("DEV#1");
|
||||||
|
|
||||||
dev.addAttr(
|
std::println("add arith RW-attr with id='{}' (val={})", id1, i);
|
||||||
"1", [&i]() -> adc_result_t<int> { return i; },
|
dev.addArithAttr(
|
||||||
|
id1, [&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;
|
||||||
});
|
});
|
||||||
|
// dev.addAttr(
|
||||||
|
// id1, [&i]() -> adc_result_t<int> { return i; },
|
||||||
|
// [&i](int ii) -> adc_error_t {
|
||||||
|
// i = ii;
|
||||||
|
// return AdcDeviceErrorCode::ERROR_OK;
|
||||||
|
// },
|
||||||
|
// std::tuple<double, int, long>{});
|
||||||
|
|
||||||
dev.addAttr("2", [&d]() -> adc_result_t<double> { return d; }, nullptr);
|
std::println("add RO-attr with id='{}' (val={})", id2, d);
|
||||||
|
dev.addAttr(id2, [&d]() -> adc_result_t<double> { return d; }, nullptr);
|
||||||
|
|
||||||
adc_result_t<int> ri = dev["1"];
|
std::println("add RW-attr with id='{}' (val={})", id3, s);
|
||||||
|
dev.addAttr(
|
||||||
|
id3, [&s]() -> adc_result_t<std::string> { return s; },
|
||||||
|
[&s](std::string const& sv) -> adc_error_t {
|
||||||
|
s = sv;
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
[&s](adc_result_t<std::string> const&) -> adc_result_t<const char*> { return s.c_str(); },
|
||||||
|
[&s](adc_result_t<const char*> const& p) mutable -> adc_result_t<std::string> {
|
||||||
|
// s = p.value();
|
||||||
|
// return s;
|
||||||
|
return std::string(p.value());
|
||||||
|
});
|
||||||
|
|
||||||
|
std::print("get '{}'-attr value as native int:\t", id1);
|
||||||
|
adc_result_t<int> ri = dev[id1];
|
||||||
if (ri) {
|
if (ri) {
|
||||||
std::println("dev[1] = {}", ri.value());
|
std::println("dev[{}] = {}", id1, ri.value());
|
||||||
} else {
|
} else {
|
||||||
std::println("cannot get dev[1] as int: {}", ri.error().message());
|
std::println("cannot get dev[{}] as int: {}", id1, ri.error().message());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto err = dev["1"] = 77;
|
int ii = 77;
|
||||||
|
std::print("set '{}'-attr value to {} as native int:\t", id1, ii);
|
||||||
|
auto err = dev[id1] = ii;
|
||||||
if (err) {
|
if (err) {
|
||||||
std::println("cannot set dev[1] as int: {}", err.message());
|
std::println("cannot set dev[{}] as int: {}", id1, err.message());
|
||||||
|
} else {
|
||||||
|
std::println("OK");
|
||||||
}
|
}
|
||||||
|
|
||||||
adc_result_t<double> rd = dev["1"];
|
std::print("get '{}'-attr value as double:\t", id1);
|
||||||
|
adc_result_t<double> rd = dev[id1];
|
||||||
if (rd) {
|
if (rd) {
|
||||||
std::println("dev[1] = {}", rd.value());
|
std::println("dev[{}] = {}", id1, rd.value());
|
||||||
} else {
|
} else {
|
||||||
std::println("cannot get dev[1] as double: {}", rd.error().message());
|
std::println("cannot get dev[{}] as double: {}", id1, rd.error().message());
|
||||||
}
|
}
|
||||||
|
|
||||||
ri = dev["1"];
|
double dd = 33.333;
|
||||||
if (ri) {
|
std::print("set '{}'-attr value to {} as double:\t", id1, dd);
|
||||||
std::println("dev[1] = {}", ri.value());
|
err = dev[id1] = dd;
|
||||||
} else {
|
|
||||||
std::println("cannot get dev[1] as int: {}", ri.error().message());
|
|
||||||
}
|
|
||||||
|
|
||||||
err = dev["2"] = 0.29817;
|
|
||||||
if (err) {
|
if (err) {
|
||||||
std::println("cannot set dev[2] as double: {}", err.message());
|
std::println("cannot set dev[{}] as double: {}", id1, err.message());
|
||||||
|
} else {
|
||||||
|
std::println("OK");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::print("get '{}'-attr value as native int:\t", id1);
|
||||||
|
ri = dev[id1];
|
||||||
|
if (ri) {
|
||||||
|
std::println("dev[{}] = {}", id1, ri.value());
|
||||||
|
} else {
|
||||||
|
std::println("cannot get dev[{}] as int: {}", id1, ri.error().message());
|
||||||
|
}
|
||||||
|
|
||||||
|
err = dev[id2] = 0.29817;
|
||||||
|
if (err) {
|
||||||
|
std::println("cannot set dev[{}] as double: {}", id2, err.message());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::println("\n");
|
||||||
|
|
||||||
|
std::print("get '{}'-attr value as native string:\t", id3);
|
||||||
|
adc_result_t<std::string> rs = dev[id3];
|
||||||
|
if (rs) {
|
||||||
|
std::println("dev[{}] = {}", id3, rs.value());
|
||||||
|
} else {
|
||||||
|
std::println("cannot get dev[{}] as string: {}", id3, rs.error().message());
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* sp = "QWERTY";
|
||||||
|
std::print("set '{}'-attr value to '{}' as const char*:\t", id3, sp);
|
||||||
|
err = dev[id3] = sp;
|
||||||
|
if (err) {
|
||||||
|
std::println("cannot set dev[{}] as const char*: {}", id3, err.message());
|
||||||
|
} else {
|
||||||
|
std::println("OK");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
31
examples/netmsg_exam.cpp
Normal file
31
examples/netmsg_exam.cpp
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#include <print>
|
||||||
|
|
||||||
|
#include <adclib/adclib_netmsg.h>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
adc::AdcNetworkMessage msg;
|
||||||
|
|
||||||
|
std::println("is ACK: {}", msg.isACK());
|
||||||
|
|
||||||
|
msg.createSET("ATTR1", snplib::snplib_serialization_params_t{}, 10, std::vector<char>{'V', 'A', 'L'});
|
||||||
|
|
||||||
|
std::println("KEY: <{}>", msg.key());
|
||||||
|
|
||||||
|
std::println("VALUE: <{}>", msg.value());
|
||||||
|
|
||||||
|
std::println("is SET: {}", msg.isSET());
|
||||||
|
|
||||||
|
std::println("is VALID: {}", msg.isValid());
|
||||||
|
|
||||||
|
|
||||||
|
std::string str{"SET ATTRQ 32.235 dwejh kd2jl"};
|
||||||
|
|
||||||
|
msg.fromCharRange(str);
|
||||||
|
|
||||||
|
std::println("KEY: <{}>", msg.key());
|
||||||
|
|
||||||
|
std::println("VALUE: <{}>", msg.value());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -60,7 +60,7 @@ namespace adc
|
|||||||
struct AdcDeviceErrorCategory : std::error_category {
|
struct AdcDeviceErrorCategory : std::error_category {
|
||||||
const char* name() const noexcept
|
const char* name() const noexcept
|
||||||
{
|
{
|
||||||
return "MCC-DESERIALIZER-ERR-CATEGORY";
|
return "ADCLIB-DEVICE-ERR-CATEGORY";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string message(int ec) const
|
std::string message(int ec) const
|
||||||
@@ -102,6 +102,10 @@ inline std::error_code make_error_code(AdcDeviceErrorCode ec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept adclib_command_exec_t = snplib::snplib_callable_c<T> && (snplib::snplib_func_traits_t<T>::arity == 0) &&
|
||||||
|
std::same_as<adc_error_t, typename snplib::snplib_func_traits_t<T>::ret_t>;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept adclib_attr_getter_c = std::same_as<T, std::nullptr_t> || requires(T t) {
|
concept adclib_attr_getter_c = std::same_as<T, std::nullptr_t> || requires(T t) {
|
||||||
{ t() } -> adc_result_c;
|
{ t() } -> adc_result_c;
|
||||||
@@ -115,10 +119,38 @@ concept adclib_attr_setter_c =
|
|||||||
|
|
||||||
// deduce value type from getter and setter
|
// deduce value type from getter and setter
|
||||||
template <adclib_attr_getter_c GT, adclib_attr_setter_c ST>
|
template <adclib_attr_getter_c GT, adclib_attr_setter_c ST>
|
||||||
using snplib_attr_value_deduced_t =
|
using adclib_attr_value_deduced_t = std::conditional_t<
|
||||||
std::conditional_t<std::is_null_pointer_v<GT>,
|
std::is_null_pointer_v<GT>,
|
||||||
std::conditional_t<std::is_null_pointer_v<ST>, void, snplib::snplib_func_arg1_t<ST>>,
|
std::conditional_t<std::is_null_pointer_v<ST>, void, std::remove_cvref_t<snplib::snplib_func_arg1_t<ST>>>,
|
||||||
typename std::invoke_result_t<GT>::value_type>;
|
typename std::invoke_result_t<GT>::value_type>;
|
||||||
|
|
||||||
|
|
||||||
|
template <adclib_attr_getter_c GT, adclib_attr_setter_c ST>
|
||||||
|
struct adclib_is_deduced_void_t {
|
||||||
|
static constexpr bool value = std::is_void_v<adclib_attr_value_deduced_t<GT, ST>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
// conversional function signature:
|
||||||
|
// "from": adc_result_t<UT> func(const adc_result_t<VT>&)
|
||||||
|
// "to": adc_result_t<VT> func(const adc_result_t<UT>&)
|
||||||
|
template <typename T, typename VT>
|
||||||
|
concept adclib_attr_conv_from_func_c =
|
||||||
|
std::same_as<T, std::nullptr_t> ||
|
||||||
|
(std::invocable<T, const adc_result_t<VT>&> && !std::is_void_v<std::invoke_result_t<T, const adc_result_t<VT>&>>);
|
||||||
|
|
||||||
|
template <typename T, typename VT>
|
||||||
|
concept adclib_attr_conv_to_func_c = std::same_as<T, std::nullptr_t> ||
|
||||||
|
(snplib::snplib_callable_c<T> && (snplib::snplib_func_traits_t<T>::arity == 1) &&
|
||||||
|
std::same_as<adc_result_t<VT>, typename snplib::snplib_func_traits_t<T>::ret_t>);
|
||||||
|
|
||||||
|
template <typename VT, adclib_attr_conv_from_func_c<VT> CONV_FROM_T, adclib_attr_conv_to_func_c<VT> CONV_TO_T>
|
||||||
|
using adclib_attr_user_deduced_t =
|
||||||
|
std::conditional_t<std::is_null_pointer_v<CONV_FROM_T>,
|
||||||
|
std::conditional_t<std::is_null_pointer_v<CONV_TO_T>,
|
||||||
|
void,
|
||||||
|
std::remove_cvref_t<snplib::snplib_func_arg1_t<CONV_TO_T>>>,
|
||||||
|
typename snplib::snplib_func_traits_t<CONV_FROM_T>::ret_t>;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <std::formattable<char> DEV_ID_T = std::string,
|
template <std::formattable<char> DEV_ID_T = std::string,
|
||||||
@@ -129,8 +161,50 @@ class AdcGenericDevice
|
|||||||
protected:
|
protected:
|
||||||
template <typename VT>
|
template <typename VT>
|
||||||
struct attr_t {
|
struct attr_t {
|
||||||
std::function<adc_result_t<VT>()> getter;
|
std::function<adc_result_t<VT>()> getter{};
|
||||||
std::function<adc_error_t(VT const&)> setter;
|
std::function<adc_error_t(VT const&)> setter{};
|
||||||
|
|
||||||
|
// template <typename UT>
|
||||||
|
// requires(requires(VT v, UT u) { v = u; } && !std::same_as<VT, UT>)
|
||||||
|
// attr_t& operator=(attr_t<UT> const& other)
|
||||||
|
// {
|
||||||
|
// std::println("ATTR::operator=");
|
||||||
|
// if (other.getter) {
|
||||||
|
// getter = [&other]() -> adc_result_t<VT> {
|
||||||
|
// auto val = other.getter();
|
||||||
|
// if (val) {
|
||||||
|
// return static_cast<VT>(val.value());
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return std::unexpected(val.error());
|
||||||
|
// };
|
||||||
|
// } else { // write-only attribute
|
||||||
|
// getter = nullptr;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (other.setter) {
|
||||||
|
// setter = [&other](VT const& v) { return other.setter(static_cast<UT>(v)); };
|
||||||
|
// } else { // read-only attribute
|
||||||
|
// setter = nullptr;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return *this;
|
||||||
|
// }
|
||||||
|
|
||||||
|
template <typename UT>
|
||||||
|
requires requires(VT v, UT u) { v = u; }
|
||||||
|
operator attr_t<UT>() const
|
||||||
|
{
|
||||||
|
return attr_t<UT>{.getter = [this]() -> adc_result_t<UT> {
|
||||||
|
auto val = getter();
|
||||||
|
if (val) {
|
||||||
|
return static_cast<UT>(val.value());
|
||||||
|
} else {
|
||||||
|
return std::unexpected(val.error());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.setter = [this](UT const& u) { return setter(static_cast<VT>(u)); }};
|
||||||
|
}
|
||||||
|
|
||||||
adc_error_t serialize(snplib::snplib_output_char_range_c auto& output,
|
adc_error_t serialize(snplib::snplib_output_char_range_c auto& output,
|
||||||
snplib::snplib_serialization_params_c auto const& params)
|
snplib::snplib_serialization_params_c auto const& params)
|
||||||
@@ -196,7 +270,7 @@ protected:
|
|||||||
template <typename VT>
|
template <typename VT>
|
||||||
adc_error_t operator=(VT&& val)
|
adc_error_t operator=(VT&& val)
|
||||||
{
|
{
|
||||||
auto attr = _dev._attrs.template get<attr_t<VT>>(_id);
|
auto attr = _dev._attrs.template get<attr_t<std::remove_cvref_t<VT>>>(_id);
|
||||||
if (attr) {
|
if (attr) {
|
||||||
if (attr.value().setter) {
|
if (attr.value().setter) {
|
||||||
return attr.value().setter(std::forward<VT>(val));
|
return attr.value().setter(std::forward<VT>(val));
|
||||||
@@ -219,10 +293,27 @@ protected:
|
|||||||
|
|
||||||
DEV_ID_T _devId;
|
DEV_ID_T _devId;
|
||||||
|
|
||||||
std::unordered_map<CMD_ID_T, std::function<void()>> _commands{};
|
// std::unordered_map<CMD_ID_T, std::function<void()>> _commands{};
|
||||||
|
std::unordered_map<CMD_ID_T, std::function<adc_error_t()>> _commands{};
|
||||||
snplib::HeterogenMap<ATTR_ID_T> _attrs{};
|
snplib::HeterogenMap<ATTR_ID_T> _attrs{};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static constexpr std::tuple<bool,
|
||||||
|
char,
|
||||||
|
short,
|
||||||
|
int,
|
||||||
|
long,
|
||||||
|
long long,
|
||||||
|
unsigned char,
|
||||||
|
unsigned short,
|
||||||
|
unsigned int,
|
||||||
|
unsigned long,
|
||||||
|
unsigned long long,
|
||||||
|
float,
|
||||||
|
double,
|
||||||
|
long double>
|
||||||
|
arithmetic_types{};
|
||||||
|
|
||||||
typedef DEV_ID_T device_id_t;
|
typedef DEV_ID_T device_id_t;
|
||||||
typedef ATTR_ID_T attr_id_t;
|
typedef ATTR_ID_T attr_id_t;
|
||||||
typedef CMD_ID_T cmd_id_t;
|
typedef CMD_ID_T cmd_id_t;
|
||||||
@@ -238,30 +329,145 @@ public:
|
|||||||
return _devId;
|
return _devId;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <snplib::snplib_callable_c ET>
|
// template <snplib::snplib_callable_c ET>
|
||||||
|
// void addCommand(CMD_ID_T id, ET&& exec_func)
|
||||||
|
// {
|
||||||
|
// _commands.emplace(std::move(id), std::forward<ET>(exec_func));
|
||||||
|
// }
|
||||||
|
|
||||||
|
template <adclib_command_exec_t ET>
|
||||||
void addCommand(CMD_ID_T id, ET&& exec_func)
|
void addCommand(CMD_ID_T id, ET&& exec_func)
|
||||||
{
|
{
|
||||||
_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, typename... VTs>
|
template <typename GT, typename ST, typename... VTs>
|
||||||
template <adclib_attr_getter_c GT, adclib_attr_setter_c ST>
|
void addAttr(ATTR_ID_T id, GT&& getter, ST&& setter, std::tuple<VTs...> = std::tuple<>{})
|
||||||
void addAttr(ATTR_ID_T id, GT&& getter, ST&& setter)
|
|
||||||
{
|
{
|
||||||
using v_t = snplib_attr_value_deduced_t<GT, ST>;
|
using v_t = adclib_attr_value_deduced_t<GT, ST>;
|
||||||
static_assert(!std::is_void_v<v_t>, "Getter and setter cannot be nullptr_t at the same time!");
|
static_assert(!std::is_void_v<v_t>, "Getter and setter cannot be nullptr_t at the same time!");
|
||||||
|
|
||||||
if constexpr (!std::is_null_pointer_v<GT> && !std::is_null_pointer_v<ST>) {
|
if constexpr (!std::is_null_pointer_v<GT> && !std::is_null_pointer_v<ST>) {
|
||||||
static_assert(std::invocable<ST, v_t const&>, "Invalid setter argument type!");
|
static_assert(std::invocable<ST, v_t const&>, "Invalid setter argument type!");
|
||||||
}
|
}
|
||||||
|
|
||||||
_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)},
|
||||||
|
std::tuple<attr_t<VTs>...>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
template <adclib_attr_getter_c GT, adclib_attr_setter_c ST, typename... FuncTs>
|
||||||
|
requires(sizeof...(FuncTs) > 1)
|
||||||
|
void addAttr(ATTR_ID_T id, GT&& getter, ST&& setter, FuncTs&&... cnv_pairs)
|
||||||
|
{
|
||||||
|
static constexpr size_t NFUNCS = sizeof...(FuncTs);
|
||||||
|
|
||||||
|
static_assert(NFUNCS % 2 == 0, "Number of conversional functions must be an even!");
|
||||||
|
|
||||||
|
using v_t = adclib_attr_value_deduced_t<GT, ST>;
|
||||||
|
static_assert(!std::is_void_v<v_t>, "Getter and setter cannot be nullptr_t at the same time!");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[... cnv_pairs_cap = std::forward<FuncTs>(cnv_pairs), id, getter_cap = std::forward<GT>(getter),
|
||||||
|
setter_cap = std::forward<ST>(setter), this]<size_t... Is>(std::index_sequence<Is...>) mutable {
|
||||||
|
// auto&& tp = std::forward_as_tuple(std::forward<FuncTs>(cnv_pairs_cap)...);
|
||||||
|
auto tp = std::forward_as_tuple(std::forward<FuncTs>(cnv_pairs_cap)...);
|
||||||
|
|
||||||
|
// static_assert(
|
||||||
|
// std::disjunction_v<adclib_is_deduced_void_t<std::tuple_element_t<Is * 2,
|
||||||
|
// decltype(tp)>,
|
||||||
|
// std::tuple_element_t<Is * 2 +
|
||||||
|
// 1, decltype(tp)>>...>,
|
||||||
|
// "Getter and setter cannot be nullptr_t at the same time!");
|
||||||
|
|
||||||
|
auto from_cnv_func = []<size_t I, snplib::snplib_tuple_c TpT>(TpT const& func_tp) {
|
||||||
|
using from_fn_t = std::decay_t<std::tuple_element_t<I, TpT>>;
|
||||||
|
using to_fn_t = std::decay_t<std::tuple_element_t<I + 1, TpT>>;
|
||||||
|
|
||||||
|
using u_t = typename adclib_attr_user_deduced_t<v_t, from_fn_t, to_fn_t>::value_type;
|
||||||
|
|
||||||
|
return [&func_tp](attr_t<v_t> const& attr) mutable -> attr_t<u_t> {
|
||||||
|
return attr_t<u_t>{
|
||||||
|
.getter = [&attr, &func_tp]() mutable -> adc_result_t<u_t> {
|
||||||
|
return std::forward<std::tuple_element_t<I, TpT>>(std::get<I>(func_tp))(attr.getter());
|
||||||
|
},
|
||||||
|
.setter = [&attr, &func_tp](u_t const& uv) mutable -> adc_error_t {
|
||||||
|
auto val = std::forward<std::tuple_element_t<I + 1, TpT>>(std::get<I + 1>(func_tp))(uv);
|
||||||
|
|
||||||
|
if (val) {
|
||||||
|
return attr.setter(val.value());
|
||||||
|
} else {
|
||||||
|
return val.error();
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
// auto from_cnv_func = []<size_t I, snplib::snplib_tuple_c TpT>(TpT&& func_tp) {
|
||||||
|
// using tp_t = std::remove_cvref_t<TpT>;
|
||||||
|
|
||||||
|
// using from_fn_t = std::decay_t<std::tuple_element_t<I, tp_t>>;
|
||||||
|
// using to_fn_t = std::decay_t<std::tuple_element_t<I + 1, tp_t>>;
|
||||||
|
|
||||||
|
// using u_t = adclib_attr_user_deduced_t<v_t, from_fn_t, to_fn_t>;
|
||||||
|
|
||||||
|
// return [func_tp_cap = std::forward<TpT>(func_tp)](attr_t<v_t> const& attr) mutable -> attr_t<u_t> {
|
||||||
|
// using tp_cap_t = decltype(func_tp_cap);
|
||||||
|
// return attr_t<u_t>{.getter = [&attr, func_tp_cap_cap = std::forward<tp_cap_t>(
|
||||||
|
// func_tp_cap)]() mutable -> adc_result_t<u_t> {
|
||||||
|
// using tp_cap_cap_t = decltype(func_tp_cap_cap);
|
||||||
|
// return std::forward<std::tuple_element_t<I, tp_cap_cap_t>>(
|
||||||
|
// std::get<I>(std::forward<tp_cap_cap_t>(func_tp_cap_cap)))(attr.getter());
|
||||||
|
// },
|
||||||
|
// .setter = [&attr, func_tp_cap_cap = std::forward<tp_cap_t>(func_tp_cap)](
|
||||||
|
// u_t const& uv) mutable -> adc_error_t {
|
||||||
|
// using tp_cap_cap_t = decltype(func_tp_cap_cap);
|
||||||
|
|
||||||
|
// auto val = std::forward<std::tuple_element_t<I + 1, tp_cap_cap_t>>(
|
||||||
|
// std::get<I + 1>(std::forward<tp_cap_cap_t>(func_tp_cap_cap)))(uv);
|
||||||
|
|
||||||
|
// if (val) {
|
||||||
|
// return attr.setter(val.value());
|
||||||
|
// } else {
|
||||||
|
// return val.error();
|
||||||
|
// }
|
||||||
|
// }};
|
||||||
|
// };
|
||||||
|
// };
|
||||||
|
|
||||||
|
auto to_cnv_func = [id, this]<size_t I, snplib::snplib_tuple_c TpT>(TpT const& func_tp) {
|
||||||
|
using from_fn_t = std::decay_t<std::tuple_element_t<I, TpT>>;
|
||||||
|
using to_fn_t = std::decay_t<std::tuple_element_t<I + 1, TpT>>;
|
||||||
|
|
||||||
|
using u_t = typename adclib_attr_user_deduced_t<v_t, from_fn_t, to_fn_t>::value_type;
|
||||||
|
|
||||||
|
return [id, this](attr_t<u_t> const&) -> attr_t<v_t> {
|
||||||
|
return _attrs.template get<attr_t<v_t>>(id).value();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
std::apply(
|
||||||
|
[this](auto&&... args) { _attrs.pushWithCnv(std::forward<decltype(args)>(args)...); },
|
||||||
|
std::tuple_cat(
|
||||||
|
std::forward_as_tuple(id, attr_t<v_t>{.getter = std::forward<decltype(getter_cap)>(getter_cap),
|
||||||
|
.setter = std::forward<decltype(setter_cap)>(setter_cap)}),
|
||||||
|
std::tuple_cat(std::forward_as_tuple(from_cnv_func.template operator()<Is>(tp),
|
||||||
|
to_cnv_func.template operator()<Is>(tp))...)));
|
||||||
|
}(std::make_index_sequence<NFUNCS / 2>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
// add attribute of one of arithmetic type
|
||||||
|
template <typename GT, typename ST>
|
||||||
|
requires std::is_arithmetic_v<adclib_attr_value_deduced_t<GT, ST>>
|
||||||
|
void addArithAttr(ATTR_ID_T id, GT&& getter, ST&& setter)
|
||||||
|
{
|
||||||
|
addAttr(std::move(id), std::forward<GT>(getter), std::forward<ST>(setter), AdcGenericDevice::arithmetic_types);
|
||||||
}
|
}
|
||||||
|
|
||||||
adc_error_t operator()(CMD_ID_T id)
|
adc_error_t operator()(CMD_ID_T id)
|
||||||
{
|
{
|
||||||
if (auto it = _commands.find(id); it != _commands.end()) {
|
if (auto it = _commands.find(id); it != _commands.end()) {
|
||||||
return (*it)();
|
// return (*it)();
|
||||||
|
return it->second();
|
||||||
}
|
}
|
||||||
|
|
||||||
return AdcDeviceErrorCode::ERROR_NO_CMD_ID;
|
return AdcDeviceErrorCode::ERROR_NO_CMD_ID;
|
||||||
|
|||||||
304
include/adclib/adclib_device1.h
Normal file
304
include/adclib/adclib_device1.h
Normal file
@@ -0,0 +1,304 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************************
|
||||||
|
* ABSTRACT DEVICE COMPONENTS LIBRARY *
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
#include <concepts>
|
||||||
|
#include <format>
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
#include <system_error>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
|
||||||
|
#include <snipplib/concepts/snplib_traits.h>
|
||||||
|
#include <snipplib/containers/snplib_hmap.h>
|
||||||
|
#include <snipplib/serialization/snplib_serialization.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "adclib_common.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace adc
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
enum class AdcDeviceErrorCode : int {
|
||||||
|
ERROR_OK,
|
||||||
|
ERROR_NO_CMD_ID,
|
||||||
|
ERROR_NO_ATTR_ID,
|
||||||
|
ERROR_RO_ATTR,
|
||||||
|
ERROR_WO_ATTR,
|
||||||
|
ERROR_ATTR_RANGE,
|
||||||
|
ERROR_SERIALIZATION,
|
||||||
|
ERROR_DESERIALIZATION,
|
||||||
|
ERROR_UNKNOWN
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace adc
|
||||||
|
|
||||||
|
namespace std
|
||||||
|
{
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class is_error_code_enum<adc::AdcDeviceErrorCode> : public true_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace std
|
||||||
|
|
||||||
|
|
||||||
|
namespace adc
|
||||||
|
{
|
||||||
|
|
||||||
|
// error category
|
||||||
|
|
||||||
|
struct AdcDeviceErrorCategory : std::error_category {
|
||||||
|
const char* name() const noexcept
|
||||||
|
{
|
||||||
|
return "ADCLIB-DEVICE-ERR-CATEGORY";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string message(int ec) const
|
||||||
|
{
|
||||||
|
AdcDeviceErrorCode err = static_cast<AdcDeviceErrorCode>(ec);
|
||||||
|
|
||||||
|
switch (err) {
|
||||||
|
case AdcDeviceErrorCode::ERROR_OK:
|
||||||
|
return "OK";
|
||||||
|
case AdcDeviceErrorCode::ERROR_NO_CMD_ID:
|
||||||
|
return "invalid command ID";
|
||||||
|
case AdcDeviceErrorCode::ERROR_NO_ATTR_ID:
|
||||||
|
return "invalid attribute ID";
|
||||||
|
case AdcDeviceErrorCode::ERROR_RO_ATTR:
|
||||||
|
return "read-only attribute";
|
||||||
|
case AdcDeviceErrorCode::ERROR_WO_ATTR:
|
||||||
|
return "write-only attribute";
|
||||||
|
case AdcDeviceErrorCode::ERROR_ATTR_RANGE:
|
||||||
|
return "value is out of attribute range ";
|
||||||
|
case AdcDeviceErrorCode::ERROR_SERIALIZATION:
|
||||||
|
return "serialization error";
|
||||||
|
case AdcDeviceErrorCode::ERROR_DESERIALIZATION:
|
||||||
|
return "deserialization error";
|
||||||
|
default:
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const AdcDeviceErrorCategory& get()
|
||||||
|
{
|
||||||
|
static const AdcDeviceErrorCategory constInst;
|
||||||
|
return constInst;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::error_code make_error_code(AdcDeviceErrorCode ec)
|
||||||
|
{
|
||||||
|
return std::error_code(static_cast<int>(ec), AdcDeviceErrorCategory::get());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept adclib_command_exec_t = snplib::snplib_callable_c<T> && (snplib::snplib_func_traits_t<T>::arity == 0) &&
|
||||||
|
std::same_as<adc_error_t, typename snplib::snplib_func_traits_t<T>::ret_t>;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept adclib_attr_getter_c = std::same_as<T, std::nullptr_t> || requires(T t) {
|
||||||
|
{ t() } -> adc_result_c;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept adclib_attr_setter_c =
|
||||||
|
std::same_as<T, std::nullptr_t> || (snplib::snplib_callable_c<T> && (snplib::snplib_func_traits_t<T>::arity >= 1) &&
|
||||||
|
std::same_as<adc_error_t, typename snplib::snplib_func_traits_t<T>::ret_t>);
|
||||||
|
|
||||||
|
|
||||||
|
// deduce value type from getter and setter
|
||||||
|
template <adclib_attr_getter_c GT, adclib_attr_setter_c ST>
|
||||||
|
using adclib_attr_value_deduced_t = std::conditional_t<
|
||||||
|
std::is_null_pointer_v<GT>,
|
||||||
|
std::conditional_t<std::is_null_pointer_v<ST>, void, std::remove_cvref_t<snplib::snplib_func_arg1_t<ST>>>,
|
||||||
|
typename std::invoke_result_t<GT>::value_type>;
|
||||||
|
|
||||||
|
|
||||||
|
template <adclib_attr_getter_c GT, adclib_attr_setter_c ST>
|
||||||
|
struct adclib_is_deduced_void_t {
|
||||||
|
static constexpr bool value = std::is_void_v<adclib_attr_value_deduced_t<GT, ST>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
// conversional function signature:
|
||||||
|
// "from": adc_result_t<UT> func(const adc_result_t<VT>&)
|
||||||
|
// "to": adc_result_t<VT> func(const adc_result_t<UT>&)
|
||||||
|
template <typename T, typename VT>
|
||||||
|
concept adclib_attr_conv_from_func_c =
|
||||||
|
std::same_as<T, std::nullptr_t> ||
|
||||||
|
(std::invocable<T, const adc_result_t<VT>&> && !std::is_void_v<std::invoke_result_t<T, const adc_result_t<VT>&>>);
|
||||||
|
|
||||||
|
template <typename T, typename VT>
|
||||||
|
concept adclib_attr_conv_to_func_c = std::same_as<T, std::nullptr_t> ||
|
||||||
|
(snplib::snplib_callable_c<T> && (snplib::snplib_func_traits_t<T>::arity == 1) &&
|
||||||
|
std::same_as<adc_result_t<VT>, typename snplib::snplib_func_traits_t<T>::ret_t>);
|
||||||
|
|
||||||
|
template <typename VT, adclib_attr_conv_from_func_c<VT> CONV_FROM_T, adclib_attr_conv_to_func_c<VT> CONV_TO_T>
|
||||||
|
using adclib_attr_user_deduced_t =
|
||||||
|
std::conditional_t<std::is_null_pointer_v<CONV_FROM_T>,
|
||||||
|
std::conditional_t<std::is_null_pointer_v<CONV_TO_T>,
|
||||||
|
void,
|
||||||
|
std::remove_cvref_t<snplib::snplib_func_arg1_t<CONV_TO_T>>>,
|
||||||
|
typename snplib::snplib_func_traits_t<CONV_FROM_T>::ret_t>;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template <std::formattable<char> DEV_ID_T = std::string,
|
||||||
|
std::formattable<char> ATTR_ID_T = std::string,
|
||||||
|
std::formattable<char> CMD_ID_T = std::string>
|
||||||
|
class AdcGenericDevice
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
template <typename VT>
|
||||||
|
using attr_getter_t = std::function<adc_result_t<VT>()>;
|
||||||
|
|
||||||
|
template <typename VT>
|
||||||
|
using attr_setter_t = std::function<adc_error_t(VT const&)>;
|
||||||
|
|
||||||
|
typedef std::vector<char> serialized_t;
|
||||||
|
typedef std::function<adc_error_t(serialized_t&)> attr_serial_func_t;
|
||||||
|
typedef std::function<adc_error_t(serialized_t const&)> attr_deserial_func_t;
|
||||||
|
|
||||||
|
struct attr_t {
|
||||||
|
attr_t(AdcGenericDevice& dev, ATTR_ID_T id) : _dev(dev), _id(std::move(id)) {}
|
||||||
|
|
||||||
|
template <typename VT>
|
||||||
|
operator adc_result_t<VT>() const
|
||||||
|
{
|
||||||
|
auto getter = _dev._attrGetter.template get<attr_getter_t<VT>>(_id);
|
||||||
|
if (getter) {
|
||||||
|
if (getter.value()) {
|
||||||
|
return getter.value()();
|
||||||
|
} else {
|
||||||
|
return std::unexpected(AdcDeviceErrorCode::ERROR_WO_ATTR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getter.error() == snplib::HeterogenMap<ATTR_ID_T>::ERROR_NO_ELEM) {
|
||||||
|
return std::unexpected(AdcDeviceErrorCode::ERROR_NO_ATTR_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallback ...
|
||||||
|
return std::unexpected(AdcDeviceErrorCode::ERROR_UNKNOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VT>
|
||||||
|
adc_error_t operator=(VT&& val)
|
||||||
|
{
|
||||||
|
auto setter = _dev._attrSetter.template get<attr_setter_t<std::remove_cvref_t<VT>>>(_id);
|
||||||
|
if (setter) {
|
||||||
|
if (setter.value()) {
|
||||||
|
return setter.value()(std::forward<VT>(val));
|
||||||
|
} else {
|
||||||
|
return AdcDeviceErrorCode::ERROR_WO_ATTR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setter.error() == snplib::HeterogenMap<ATTR_ID_T>::ERROR_NO_ELEM) {
|
||||||
|
return AdcDeviceErrorCode::ERROR_NO_ATTR_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallback ...
|
||||||
|
return AdcDeviceErrorCode::ERROR_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
AdcGenericDevice& _dev;
|
||||||
|
ATTR_ID_T _id;
|
||||||
|
};
|
||||||
|
|
||||||
|
DEV_ID_T _devId;
|
||||||
|
|
||||||
|
std::unordered_map<CMD_ID_T, std::function<adc_error_t()>> _commands{};
|
||||||
|
std::unordered_map<ATTR_ID_T, attr_t> _attrs{};
|
||||||
|
|
||||||
|
snplib::HeterogenMap<ATTR_ID_T> _attrGetter{};
|
||||||
|
snplib::HeterogenMap<ATTR_ID_T> _attrSetter{};
|
||||||
|
|
||||||
|
public:
|
||||||
|
static constexpr std::tuple<bool,
|
||||||
|
char,
|
||||||
|
short,
|
||||||
|
int,
|
||||||
|
long,
|
||||||
|
long long,
|
||||||
|
unsigned char,
|
||||||
|
unsigned short,
|
||||||
|
unsigned int,
|
||||||
|
unsigned long,
|
||||||
|
unsigned long long,
|
||||||
|
float,
|
||||||
|
double,
|
||||||
|
long double>
|
||||||
|
arithmetic_types{};
|
||||||
|
|
||||||
|
typedef DEV_ID_T device_id_t;
|
||||||
|
typedef ATTR_ID_T attr_id_t;
|
||||||
|
typedef CMD_ID_T cmd_id_t;
|
||||||
|
|
||||||
|
enum AttrAccessType { ATTR_ACCESS_RW, ATTR_ACCESS_RO, ATTR_ACCESS_WO };
|
||||||
|
|
||||||
|
AdcGenericDevice(device_id_t id) : _devId(id) {}
|
||||||
|
|
||||||
|
virtual ~AdcGenericDevice() = default;
|
||||||
|
|
||||||
|
device_id_t id() const
|
||||||
|
{
|
||||||
|
return _devId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// template <snplib::snplib_callable_c ET>
|
||||||
|
// void addCommand(CMD_ID_T id, ET&& exec_func)
|
||||||
|
// {
|
||||||
|
// _commands.emplace(std::move(id), std::forward<ET>(exec_func));
|
||||||
|
// }
|
||||||
|
|
||||||
|
template <adclib_command_exec_t ET>
|
||||||
|
void addCommand(CMD_ID_T id, ET&& exec_func)
|
||||||
|
{
|
||||||
|
_commands.emplace(std::move(id), std::forward<ET>(exec_func));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename GT, typename ST, typename... VTs>
|
||||||
|
void addAttr(ATTR_ID_T id, GT&& getter, ST&& setter, std::tuple<VTs...> = std::tuple<>{})
|
||||||
|
{
|
||||||
|
using v_t = adclib_attr_value_deduced_t<GT, ST>;
|
||||||
|
static_assert(!std::is_void_v<v_t>, "Getter and setter cannot be nullptr_t at the same time!");
|
||||||
|
|
||||||
|
if constexpr (!std::is_null_pointer_v<GT> && !std::is_null_pointer_v<ST>) {
|
||||||
|
static_assert(std::invocable<ST, v_t const&>, "Invalid setter argument type!");
|
||||||
|
}
|
||||||
|
|
||||||
|
_attrGetter.push(id, attr_getter_t<std::remove_cvref_t<GT>>(std::forward<GT>(getter)),
|
||||||
|
std::tuple<attr_getter_t<VTs>...>{});
|
||||||
|
|
||||||
|
_attrSetter.push(id, attr_setter_t<std::remove_cvref_t<ST>>(std::forward<ST>(setter)),
|
||||||
|
std::tuple<attr_setter_t<VTs>...>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
template <adclib_attr_getter_c GT, adclib_attr_setter_c ST, typename... FuncTs>
|
||||||
|
requires(sizeof...(FuncTs) > 1)
|
||||||
|
void addAttr(ATTR_ID_T id, GT&& getter, ST&& setter, FuncTs&&... cnv_pairs)
|
||||||
|
{
|
||||||
|
static constexpr size_t NFUNCS = sizeof...(FuncTs);
|
||||||
|
|
||||||
|
static_assert(NFUNCS % 2 == 0, "Number of conversional functions must be an even!");
|
||||||
|
|
||||||
|
using v_t = adclib_attr_value_deduced_t<GT, ST>;
|
||||||
|
static_assert(!std::is_void_v<v_t>, "Getter and setter cannot be nullptr_t at the same time!");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace adc
|
||||||
179
include/adclib/adclib_netmsg.h
Normal file
179
include/adclib/adclib_netmsg.h
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <snipplib/utils/snplib_keyvalue_expr.h>
|
||||||
|
|
||||||
|
namespace adc
|
||||||
|
{
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
static constexpr std::string_view ADCLIB_NETMSG_KEYWORD_PARAM_DELIM{" "};
|
||||||
|
static constexpr std::string_view ADCLIB_NETMSG_PARAM_PARAM_DELIM{" "};
|
||||||
|
|
||||||
|
/* network message valid keywords */
|
||||||
|
//
|
||||||
|
static constexpr std::string_view ADCLIB_NETMSG_KEYWORD_ACK{"ACK"};
|
||||||
|
|
||||||
|
// error message
|
||||||
|
static constexpr std::string_view ADCLIB_NETMSG_KEYWORD_ERR{"ERR"};
|
||||||
|
|
||||||
|
// set device attribute value
|
||||||
|
static constexpr std::string_view ADCLIB_NETMSG_KEYWORD_SET{"SET"};
|
||||||
|
|
||||||
|
// get device attribute value
|
||||||
|
static constexpr std::string_view ADCLIB_NETMSG_KEYWORD_GET{"GET"};
|
||||||
|
|
||||||
|
// execute device command
|
||||||
|
static constexpr std::string_view ADCLIB_NETMSG_KEYWORD_CMD{"CMD"};
|
||||||
|
|
||||||
|
|
||||||
|
static constexpr std::array ADCLIB_NETMSG_VALID_KEYWORDS{ADCLIB_NETMSG_KEYWORD_ACK, ADCLIB_NETMSG_KEYWORD_ERR,
|
||||||
|
ADCLIB_NETMSG_KEYWORD_SET, ADCLIB_NETMSG_KEYWORD_GET,
|
||||||
|
ADCLIB_NETMSG_KEYWORD_CMD};
|
||||||
|
|
||||||
|
|
||||||
|
template <snplib::snplib_char_range_c CharRangeT = std::vector<char>>
|
||||||
|
class AdcNetworkMessage final : protected snplib::snplib_keyvalue_expr_t<CharRangeT>
|
||||||
|
{
|
||||||
|
typedef snplib::snplib_keyvalue_expr_t<CharRangeT> base_t;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using typename base_t::error_t;
|
||||||
|
|
||||||
|
using base_t::isValid;
|
||||||
|
using base_t::key;
|
||||||
|
using base_t::value;
|
||||||
|
using base_t::valueSeq;
|
||||||
|
|
||||||
|
AdcNetworkMessage() = default;
|
||||||
|
|
||||||
|
bool isACK() const
|
||||||
|
{
|
||||||
|
return std::ranges::equal(this->_key, ADCLIB_NETMSG_KEYWORD_ACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isERR() const
|
||||||
|
{
|
||||||
|
return std::ranges::equal(this->_key, ADCLIB_NETMSG_KEYWORD_ERR);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isCMD() const
|
||||||
|
{
|
||||||
|
return std::ranges::equal(this->_key, ADCLIB_NETMSG_KEYWORD_CMD);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isSET() const
|
||||||
|
{
|
||||||
|
return std::ranges::equal(this->_key, ADCLIB_NETMSG_KEYWORD_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isGET() const
|
||||||
|
{
|
||||||
|
return std::ranges::equal(this->_key, ADCLIB_NETMSG_KEYWORD_GET);
|
||||||
|
}
|
||||||
|
|
||||||
|
error_t fromCharRange(snplib::snplib_input_char_range_c auto&& bytes)
|
||||||
|
requires(!std::same_as<CharRangeT, std::remove_cvref_t<decltype(bytes)>>)
|
||||||
|
{
|
||||||
|
auto err = fromCharRange(
|
||||||
|
std::forward<decltype(bytes)>(bytes),
|
||||||
|
{.keyval_delim = ADCLIB_NETMSG_KEYWORD_PARAM_DELIM, .valseq_delim = ADCLIB_NETMSG_PARAM_PARAM_DELIM});
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!std::ranges::contains(ADCLIB_NETMSG_VALID_KEYWORDS, key())) {
|
||||||
|
this->_isValid = false;
|
||||||
|
// return an error here!!!
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
error_t fromCharRange(CharRangeT& bytes)
|
||||||
|
{
|
||||||
|
auto err = base_t::fromCharRange(bytes, {.keyval_delim = ADCLIB_NETMSG_KEYWORD_PARAM_DELIM,
|
||||||
|
.valseq_delim = ADCLIB_NETMSG_PARAM_PARAM_DELIM});
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!std::ranges::contains(ADCLIB_NETMSG_VALID_KEYWORDS, key())) {
|
||||||
|
this->_isValid = false;
|
||||||
|
// return an error here!!!
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
error_t createACK()
|
||||||
|
{
|
||||||
|
return this->setKey(ADCLIB_NETMSG_KEYWORD_ACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
error_t createERR(error_t err)
|
||||||
|
{
|
||||||
|
return this->setKeyValue(ADCLIB_NETMSG_KEYWORD_ERR, err.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <snplib::snplib_serializable_c ATTR_NAME_T, typename... ArgTs>
|
||||||
|
requires(sizeof...(ArgTs) > 0)
|
||||||
|
error_t createSET(ATTR_NAME_T&& attr_name, ArgTs&&... args)
|
||||||
|
{
|
||||||
|
this->_isValid = false;
|
||||||
|
|
||||||
|
auto err = this->setKeyValue(ADCLIB_NETMSG_KEYWORD_SET, std::forward<ATTR_NAME_T>(attr_name));
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = this->appendValue(std::forward<ArgTs>(args)...);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->_isValid = true;
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <snplib::snplib_serializable_c ATTR_NAME_T, typename... ArgTs>
|
||||||
|
error_t createGET(ATTR_NAME_T&& attr_name, ArgTs&&... args)
|
||||||
|
{
|
||||||
|
this->_isValid = false;
|
||||||
|
|
||||||
|
auto err = this->setKeyValue(ADCLIB_NETMSG_KEYWORD_GET, std::forward<ATTR_NAME_T>(attr_name));
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->_isValid = true;
|
||||||
|
|
||||||
|
if constexpr (sizeof...(ArgTs)) {
|
||||||
|
err = this->appendValue(std::forward<ArgTs>(args)...);
|
||||||
|
if (err) {
|
||||||
|
this->_isValid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <snplib::snplib_serializable_c CMD_NAME_T>
|
||||||
|
error_t createCMD(CMD_NAME_T&& cmd_name)
|
||||||
|
{
|
||||||
|
this->_isValid = false;
|
||||||
|
|
||||||
|
auto err = this->setKeyValue(ADCLIB_NETMSG_KEYWORD_CMD, std::forward<CMD_NAME_T>(cmd_name));
|
||||||
|
if (!err) {
|
||||||
|
this->_isValid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace adc
|
||||||
Reference in New Issue
Block a user