diff --git a/examples/device_exam.cpp b/examples/device_exam.cpp index 6dc2c50..eb2de4f 100644 --- a/examples/device_exam.cpp +++ b/examples/device_exam.cpp @@ -21,6 +21,7 @@ int main() i = ii; return AdcDeviceErrorCode::ERROR_OK; }); + // dev.addAttr( // id1, [&i]() -> adc_result_t { return i; }, // [&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 { return s; }, + [&s](std::string const& sv) -> adc_error_t { + s = sv; + return {}; + }); + std::print("get '{}'-attr value as native int:\t", id1); adc_result_t ri = dev[id1]; if (ri) { @@ -115,6 +124,14 @@ int main() 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; } \ No newline at end of file diff --git a/include/adclib/adclib_device1.h b/include/adclib/adclib_device1.h index ba1961e..c330485 100644 --- a/include/adclib/adclib_device1.h +++ b/include/adclib/adclib_device1.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -223,62 +224,75 @@ protected: std::unordered_map> _commands{}; std::unordered_map _attrs{}; - // snplib::HeterogenMap _attrGetter{}; - // snplib::HeterogenMap _attrSetter{}; snplib::hmap _attrGetter{}; snplib::hmap _attrSetter{}; - template - requires requires(std::invoke_result_t v, std::invoke_result_t u) { u = v; } - inline static auto default_cnv_from_func = [](GT const& g) -> adc_result_t { - using u_t = std::invoke_result_t; + // default convert functions for char-range types - return [g]() -> adc_result_t { - auto v = g(); - - if (v) { - return static_cast(v.value()); - } - - return v.error(); - }; + template + requires((snplib::snplib_char_range_c || snplib::snplib_pointer_to_char_c) && + (snplib::snplib_char_range_c || snplib::snplib_pointer_to_char_c)) + static inline std::function(VR const&)> default_char_range_conv_from = [](VR const& val) + -> adc_result_t { + if constexpr (std::same_as) { + return val; + } else if constexpr (std::constructible_from) { + return UR(val); + } else if constexpr (std::is_pointer_v>) { // char*, const char*, char[] + return default_char_range_conv_from(std::string_view(val)); + } else if constexpr (std::constructible_from, std::ranges::sentinel_t>) { + return UR(val.begin(), val.end()); + } else if constexpr (std::constructible_from, + std::ranges::const_sentinel_t>) { + return UR(val.cbegin(), val.cend()); + } else if constexpr (std::same_as && std::is_pointer_v) { + return val.data(); + } else { + static_assert(false, "UNSUPPORTED CHAR-RANGE TYPES!"); + } }; - template - requires requires(std::invoke_result_t v, std::invoke_result_t u) { v = u; } - inline static auto default_cnv_to_func = [](UGT const& g) -> adc_result_t { - using v_t = std::invoke_result_t; - - return [g]() -> adc_result_t { - auto v = g(); - - if (v) { - return static_cast(v.value()); - } - - return v.error(); - }; - }; + template + static inline std::function(UR const&)> default_char_range_conv_to = + default_char_range_conv_from; public: - static constexpr std::tuple + inline static constexpr std::tuple arithmetic_types{}; + typedef std::tuple + arithmetics_t; + + typedef std::tuple, std::list, 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> void addArithAttr(ATTR_ID_T id, GT&& getter, ST&& setter) { - addAttr(std::move(id), std::forward(getter), std::forward(setter), AdcGenericDevice::arithmetic_types); + // addAttr(std::move(id), std::forward(getter), std::forward(setter), + // AdcGenericDevice::arithmetic_types); + addAttr(std::move(id), std::forward(getter), std::forward(setter), AdcGenericDevice::arithmetics_t{}); + } + + // add attribute of char-range type + template + requires snplib::snplib_char_range_c> + void addCharRangeAttr(ATTR_ID_T id, GT&& getter, ST&& setter) + { + using v_t = adclib_attr_value_deduced_t; + static_assert(!std::is_void_v, "Getter and setter cannot be nullptr_t at the same time!"); + + if constexpr (!std::is_null_pointer_v && !std::is_null_pointer_v) { + static_assert(std::invocable, "Invalid setter argument type!"); + } + + [&id, getter_cap = std::forward(getter), setter_cap = std::forward(setter), + this](std::index_sequence) mutable { + std::apply( + [this](auto&&... args) { addAttr(std::forward(args)...); }, + std::tuple_cat( + std::forward_as_tuple(id, std::forward(getter_cap), + std::forward(setter_cap)), + std::tuple_cat(std::forward_as_tuple( + default_char_range_conv_from>, + default_char_range_conv_to>)...))); + }(std::make_index_sequence>{}); } adc_error_t operator()(CMD_ID_T id)