This commit is contained in:
Timur A. Fatkhullin 2024-05-02 23:51:11 +03:00
parent 0d64e0cf44
commit 6de9127e58
5 changed files with 195 additions and 2 deletions

View File

@ -25,6 +25,9 @@ if (BUILD_TESTS)
set(VALUEHOLDER_TEST_APP adc_valueholder_test)
add_executable(${VALUEHOLDER_TEST_APP} tests/adc_valueholder_test.cpp)
set(DEVATTR_TEST_APP adc_devattr_test)
add_executable(${DEVATTR_TEST_APP} tests/adc_devattr_test.cpp)
if (NOT doctest_FOUND)
include(FetchContent)
FetchContent_Declare(

View File

@ -36,7 +36,9 @@ static ValueT AdcFromChars(R&& range)
#ifdef _LIBCPP_VERSION // clang's libc++ does not have floating-point overloads for std::from_chars
if constexpr (traits::adc_is_any_v<v_t, char, int, long, long long, __int128>) {
#else
if constexpr (traits::adc_is_any_of_v<v_t, char, int, long, long long, __int128, float, double, long double>) {
if constexpr (traits::adc_is_any_of_v<v_t, unsigned char, char, unsigned short, short, unsigned long, long,
unsigned long long, long long, unsigned int, int, unsigned __int128, __int128,
float, double, long double>) {
#endif
v_t v;

View File

@ -47,7 +47,7 @@ namespace adc
struct AdcValueHolderErrorCategory : public std::error_category {
AdcValueHolderErrorCategory() : std::error_category() {}
const char* name() const noexcept { return "DEVA_DEVICE_ATTRIBUTE"; }
const char* name() const noexcept { return "ADC_VALUEHOLDER_CATEGORY"; }
std::string message(int ec) const
{
@ -404,6 +404,8 @@ protected:
}
public:
typedef SerializedT serialized_t;
/* CONSTRUCTORS AND DESTRUCTOR */
template <typename GT,

View File

@ -1 +1,143 @@
#pragma once
/*
ABSTRACT DEVICE COMPONENTS LIBRARY
*/
#include "../common/adc_value.h"
namespace adc
{
template <typename IdentT, typename SerializedT = std::string>
class AdcDeviceAttribute : public AdcSerializingValueHolder<SerializedT>
{
using base_t = AdcSerializingValueHolder<SerializedT>;
template <typename T>
using ret_value_t = base_t::template ret_value_t<T>;
public:
typedef IdentT ident_t;
typedef SerializedT serialized_t;
enum AccessType { ReadOnly, WriteOnly, ReadWrite };
template <typename T>
constexpr static T DummyGetter()
{
return std::declval<T>();
}
template <typename T>
constexpr static void DummySetter(const T&)
{
}
template <typename T>
constexpr static SerializedT DummySerializer(const T&)
{
return std::declval<SerializedT>();
}
template <typename T>
constexpr static T DummyDeserializer(const SerializedT&)
{
return std::declval<T>();
}
/* CONSTRUCTORS AND DESTRUCTOR */
// general read-write attribute constructor
template <typename GT,
typename ST,
typename VALT = ret_value_t<GT>,
typename VT = decltype(AdcValueHolder::AdcValueHolderDummyValidator<VALT>),
typename SRT = decltype(utils::AdcDefaultValueConverter<>::serialize<SerializedT, VALT>),
typename DSRT = decltype(utils::AdcDefaultValueConverter<>::deserialize<VALT, SerializedT>)>
AdcDeviceAttribute(const IdentT& ident,
AccessType access_type,
GT&& getter,
ST&& setter,
VT&& validator = AdcValueHolder::AdcValueHolderDummyValidator<VALT>,
SRT&& serializer = utils::AdcDefaultValueConverter<>::serialize<SerializedT, VALT>,
DSRT&& deserializer = utils::AdcDefaultValueConverter<>::deserialize<VALT, SerializedT>)
requires std::invocable<GT> && std::invocable<ST, const VALT&> && std::predicate<VT, const VALT&> &&
std::invocable<SRT, const VALT&> && std::invocable<DSRT, const SerializedT&>
: base_t(std::forward<GT>(getter),
std::forward<ST>(setter),
std::forward<VT>(validator),
std::forward<SRT>(serializer),
std::forward<DSRT>(deserializer)),
_ident(ident),
_accessType(access_type)
{
}
// read-only attribute constructor
template <typename GT,
typename VALT = ret_value_t<GT>,
typename SRT = decltype(utils::AdcDefaultValueConverter<>::serialize<SerializedT, VALT>)>
AdcDeviceAttribute(const IdentT& ident,
GT&& getter,
SRT&& serializer = utils::AdcDefaultValueConverter<>::serialize<SerializedT, VALT>)
requires std::invocable<GT> && std::invocable<SRT, const VALT&>
: AdcDeviceAttribute(ident,
ReadOnly,
std::forward<GT>(getter),
AdcDeviceAttribute::DummySetter<VALT>,
AdcValueHolder::AdcValueHolderDummyValidator<VALT>,
std::forward<SRT>(serializer),
AdcDeviceAttribute::DummyDeserializer<VALT>)
{
}
// write-only attribute constructor
template <typename ST,
typename VALT = std::decay_t<traits::adc_func_arg1_t<ST>>,
typename DSRT = decltype(utils::AdcDefaultValueConverter<>::deserialize<VALT, SerializedT>)>
AdcDeviceAttribute(const IdentT& ident,
ST&& setter,
std::predicate<const VALT&> auto&& validator,
DSRT&& deserializer = utils::AdcDefaultValueConverter<>::deserialize<VALT, SerializedT>)
requires std::invocable<DSRT, const SerializedT&>
: AdcDeviceAttribute(ident,
WriteOnly,
AdcDeviceAttribute::DummyGetter<VALT>,
std::forward<ST>(setter),
std::forward<decltype(validator)>(validator),
AdcDeviceAttribute::DummySerializer<VALT>,
std::forward<DSRT>(deserializer))
{
}
// constructor of attribute with trivially casting type converters
template <typename... TrivCastTs, typename... Ts>
AdcDeviceAttribute(const std::tuple<TrivCastTs...>&, Ts&&... ctor_args)
: AdcDeviceAttribute(std::forward<Ts>(ctor_args)...)
{
}
virtual ~AdcDeviceAttribute() = default;
IdentT ident() const { return _ident; }
AccessType accessType() const { return _accessType; }
using base_t::operator=;
protected:
IdentT _ident;
AccessType _accessType;
};
} // namespace adc

View File

@ -0,0 +1,44 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include <doctest/doctest.h>
#include <iostream>
#include "../device/adc_device_attribute.h"
using namespace adc;
template <typename T>
struct V {
static T getter() { return _v; }
static void setter(const T& v) { _v = v; }
static bool validator(const T& v)
{
if (v < 1)
return false;
else
return true;
}
private:
inline static T _v = 1;
};
TEST_CASE("[ADC DEVICE ATTRIBUTE]")
{
double av = -10;
using vv = V<unsigned>;
using attr_t = AdcDeviceAttribute<std::string_view>;
// attr_t attr(AdcValueHolder::_defaultTrivialConvTypes, "ATTR_A", attr_t::ReadWrite, vv::getter, vv::setter,
// vv::validator);
attr_t attr("ATTR_A", attr_t::ReadWrite, vv::getter, vv::setter, vv::validator);
// attr = 10.7;
// av = attr;
// std::cout << "ATTR = " << av << "\n";
std::cout << "ATTR = " << (unsigned)attr << "\n";
}