This commit is contained in:
2026-09-08 17:21:31 +03:00
parent a2ef872d8d
commit 39fa33b472
2 changed files with 104 additions and 45 deletions

View File

@@ -21,6 +21,7 @@ int main()
i = ii; i = ii;
return AdcDeviceErrorCode::ERROR_OK; return AdcDeviceErrorCode::ERROR_OK;
}); });
// dev.addAttr( // dev.addAttr(
// id1, [&i]() -> adc_result_t<int> { return i; }, // id1, [&i]() -> adc_result_t<int> { return i; },
// [&i](int ii) -> adc_error_t { // [&i](int ii) -> adc_error_t {
@@ -49,6 +50,14 @@ int main()
// // } // // }
// ); // );
std::println("add RW-attr with id='{}' (val={})", id3, s);
dev.addCharRangeAttr(
id3, [&s]() -> adc_result_t<std::string> { return s; },
[&s](std::string const& sv) -> adc_error_t {
s = sv;
return {};
});
std::print("get '{}'-attr value as native int:\t", id1); std::print("get '{}'-attr value as native int:\t", id1);
adc_result_t<int> ri = dev[id1]; adc_result_t<int> ri = dev[id1];
if (ri) { if (ri) {
@@ -115,6 +124,14 @@ int main()
std::println("OK"); std::println("OK");
} }
std::print("get '{}'-attr value as native string:\t", id3);
rs = dev[id3];
if (rs) {
std::println("dev[{}] = {}", id3, rs.value());
} else {
std::println("cannot get dev[{}] as string: {}", id3, rs.error().message());
}
return 0; return 0;
} }

View File

@@ -9,6 +9,7 @@
#include <concepts> #include <concepts>
#include <format> #include <format>
#include <functional> #include <functional>
#include <list>
#include <string> #include <string>
#include <system_error> #include <system_error>
#include <type_traits> #include <type_traits>
@@ -223,62 +224,75 @@ protected:
std::unordered_map<CMD_ID_T, std::function<adc_error_t()>> _commands{}; std::unordered_map<CMD_ID_T, std::function<adc_error_t()>> _commands{};
std::unordered_map<ATTR_ID_T, attr_t> _attrs{}; std::unordered_map<ATTR_ID_T, attr_t> _attrs{};
// snplib::HeterogenMap<ATTR_ID_T> _attrGetter{};
// snplib::HeterogenMap<ATTR_ID_T> _attrSetter{};
snplib::hmap<ATTR_ID_T> _attrGetter{}; snplib::hmap<ATTR_ID_T> _attrGetter{};
snplib::hmap<ATTR_ID_T> _attrSetter{}; snplib::hmap<ATTR_ID_T> _attrSetter{};
template <typename GT, typename UGT> // default convert functions for char-range types
requires requires(std::invoke_result_t<GT> v, std::invoke_result_t<UGT> u) { u = v; }
inline static auto default_cnv_from_func = [](GT const& g) -> adc_result_t<UGT> {
using u_t = std::invoke_result_t<UGT>;
return [g]() -> adc_result_t<u_t> { template <typename VR, typename UR>
auto v = g(); requires((snplib::snplib_char_range_c<VR> || snplib::snplib_pointer_to_char_c<VR>) &&
(snplib::snplib_char_range_c<UR> || snplib::snplib_pointer_to_char_c<UR>))
if (v) { static inline std::function<adc_result_t<UR>(VR const&)> default_char_range_conv_from = [](VR const& val)
return static_cast<u_t>(v.value()); -> adc_result_t<UR> {
} if constexpr (std::same_as<VR, UR>) {
return val;
return v.error(); } else if constexpr (std::constructible_from<UR, VR>) {
}; return UR(val);
} else if constexpr (std::is_pointer_v<std::decay_t<VR>>) { // char*, const char*, char[]
return default_char_range_conv_from<std::string_view, UR>(std::string_view(val));
} else if constexpr (std::constructible_from<UR, std::ranges::iterator_t<VR>, std::ranges::sentinel_t<VR>>) {
return UR(val.begin(), val.end());
} else if constexpr (std::constructible_from<UR, std::ranges::const_iterator_t<VR>,
std::ranges::const_sentinel_t<VR>>) {
return UR(val.cbegin(), val.cend());
} else if constexpr (std::same_as<VR, std::string> && std::is_pointer_v<UR>) {
return val.data();
} else {
static_assert(false, "UNSUPPORTED CHAR-RANGE TYPES!");
}
}; };
template <typename GT, typename UGT> template <typename VR, typename UR>
requires requires(std::invoke_result_t<GT> v, std::invoke_result_t<UGT> u) { v = u; } static inline std::function<adc_result_t<VR>(UR const&)> default_char_range_conv_to =
inline static auto default_cnv_to_func = [](UGT const& g) -> adc_result_t<GT> { default_char_range_conv_from<UR, VR>;
using v_t = std::invoke_result_t<GT>;
return [g]() -> adc_result_t<v_t> {
auto v = g();
if (v) {
return static_cast<v_t>(v.value());
}
return v.error();
};
};
public: public:
static constexpr std::tuple<bool, inline static constexpr std::tuple<bool,
char, char,
short, short,
int, int,
long, long,
long long, long long,
unsigned char, unsigned char,
unsigned short, unsigned short,
unsigned int, unsigned int,
unsigned long, unsigned long,
unsigned long long, unsigned long long,
float, float,
double, double,
long double> long double>
arithmetic_types{}; arithmetic_types{};
typedef std::tuple<bool,
char,
short,
int,
long,
long long,
unsigned char,
unsigned short,
unsigned int,
unsigned long,
unsigned long long,
float,
double,
long double>
arithmetics_t;
typedef std::tuple<std::string, std::string_view, std::vector<char>, std::list<char>, const char*> char_ranges_t;
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;
@@ -477,7 +491,35 @@ public:
requires std::is_arithmetic_v<adclib_attr_value_deduced_t<GT, ST>> requires std::is_arithmetic_v<adclib_attr_value_deduced_t<GT, ST>>
void addArithAttr(ATTR_ID_T id, GT&& getter, ST&& setter) 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); // addAttr(std::move(id), std::forward<GT>(getter), std::forward<ST>(setter),
// AdcGenericDevice::arithmetic_types);
addAttr(std::move(id), std::forward<GT>(getter), std::forward<ST>(setter), AdcGenericDevice::arithmetics_t{});
}
// add attribute of char-range type
template <typename GT, typename ST>
requires snplib::snplib_char_range_c<adclib_attr_value_deduced_t<GT, ST>>
void addCharRangeAttr(ATTR_ID_T id, GT&& getter, ST&& setter)
{
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!");
}
[&id, getter_cap = std::forward<GT>(getter), setter_cap = std::forward<ST>(setter),
this]<size_t... Is>(std::index_sequence<Is...>) mutable {
std::apply(
[this](auto&&... args) { addAttr(std::forward<decltype(args)>(args)...); },
std::tuple_cat(
std::forward_as_tuple(id, std::forward<decltype(getter_cap)>(getter_cap),
std::forward<decltype(setter_cap)>(setter_cap)),
std::tuple_cat(std::forward_as_tuple(
default_char_range_conv_from<v_t, std::tuple_element_t<Is, AdcGenericDevice::char_ranges_t>>,
default_char_range_conv_to<v_t,
std::tuple_element_t<Is, AdcGenericDevice::char_ranges_t>>)...)));
}(std::make_index_sequence<std::tuple_size_v<AdcGenericDevice::char_ranges_t>>{});
} }
adc_error_t operator()(CMD_ID_T id) adc_error_t operator()(CMD_ID_T id)