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

@@ -9,6 +9,7 @@
#include <concepts>
#include <format>
#include <functional>
#include <list>
#include <string>
#include <system_error>
#include <type_traits>
@@ -223,62 +224,75 @@ protected:
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{};
snplib::hmap<ATTR_ID_T> _attrGetter{};
snplib::hmap<ATTR_ID_T> _attrSetter{};
template <typename GT, typename UGT>
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>;
// default convert functions for char-range types
return [g]() -> adc_result_t<u_t> {
auto v = g();
if (v) {
return static_cast<u_t>(v.value());
}
return v.error();
};
template <typename VR, typename UR>
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>))
static inline std::function<adc_result_t<UR>(VR const&)> default_char_range_conv_from = [](VR const& val)
-> adc_result_t<UR> {
if constexpr (std::same_as<VR, UR>) {
return val;
} 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>
requires requires(std::invoke_result_t<GT> v, std::invoke_result_t<UGT> u) { v = u; }
inline static auto default_cnv_to_func = [](UGT const& g) -> adc_result_t<GT> {
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();
};
};
template <typename VR, typename UR>
static inline std::function<adc_result_t<VR>(UR const&)> default_char_range_conv_to =
default_char_range_conv_from<UR, VR>;
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>
inline 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 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 ATTR_ID_T attr_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>>
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)