#pragma once /* ABSTRACT DEVICE COMPONENTS LIBRARY */ #include #include #include "adc_traits.h" namespace adc { // error codes enum class AdcValueHolderErrorCode : int { ERROR_OK, ERROR_NO_CONV_FUNC, ERROR_INTERNAL_TYPE_MISMATCH, ERROR_VALUE_IS_NOT_VALID }; } // namespace adc namespace std { template <> class is_error_code_enum : public true_type { }; } // namespace std namespace adc { // error category struct AdcValueHolderErrorCategory : public std::error_category { AdcValueHolderErrorCategory() : std::error_category() {} const char* name() const noexcept { return "DEVA_DEVICE_ATTRIBUTE"; } std::string message(int ec) const { AdcValueHolderErrorCode err = static_cast(ec); switch (err) { case AdcValueHolderErrorCode::ERROR_OK: return "OK"; case AdcValueHolderErrorCode::ERROR_NO_CONV_FUNC: return "conversion function is not defined"; case AdcValueHolderErrorCode::ERROR_INTERNAL_TYPE_MISMATCH: return "try to setup default conversion function for invalid type (internal type mismatch)"; case AdcValueHolderErrorCode::ERROR_VALUE_IS_NOT_VALID: return "user value is not valid"; default: return "UNKNOWN"; } } static const AdcValueHolderErrorCategory& get() { static const AdcValueHolderErrorCategory constInst; return constInst; } }; inline std::error_code make_error_code(AdcValueHolderErrorCode ec) { return std::error_code(static_cast(ec), AdcValueHolderErrorCategory::get()); } /* GENERAL-PURPOSE VALUE HOLDER CLASS WITH OPTIONAL VALIDATOR */ class AdcValueHolder { protected: template inline static std::unordered_map> _getterFunc{}; template inline static std::unordered_map> _setterFunc{}; void init(std::invocable<> auto&& getter, std::invocable&> auto&& setter, std::predicate&> auto&& validator) { using value_t = traits::adc_retval_t; static_assert(!std::is_same_v, "THE getter MUST NOT RETURN void TYPE!!!"); using g_t = decltype(getter); using s_t = decltype(setter); using vld_t = decltype(validator); _getterFunc[this] = [wrapper = traits::adc_pf_wrapper(std::forward(getter))]() { return std::get<0>(wrapper)(); }; _setterFunc[this] = [wrapper = traits::adc_pf_wrapper(std::forward(setter), std::forward(validator))](const value_t& val) { if (std::get<1>(wrapper)(val)) { std::get<0>(wrapper)(val); } else { throw std::system_error(AdcValueHolderErrorCode::ERROR_VALUE_IS_NOT_VALID); } }; } public: // default trivial types (just arithmetic ones) constexpr static std::tuple _defaultTrivialConvTypes{}; // always-true validator // constexpr static auto AdcValueHolderDummyValidator = [](const auto&) { return true; }; template constexpr static bool AdcValueHolderDummyValidator(const VT&) { return true; }; /* CONSTRUCTORS AND DESTRUCTOR */ template , typename VT = decltype(AdcValueHolder::AdcValueHolderDummyValidator)> AdcValueHolder(GT&& getter, std::invocable auto&& setter, VT&& validator = AdcValueHolder::AdcValueHolderDummyValidator) requires std::invocable && std::predicate { init(std::forward(getter), std::forward(setter), std::forward(validator)); } template AdcValueHolder(std::invocable<> auto&& getter, std::invocable&> auto&& setter, std::predicate&> auto&& validator, const std::tuple& /* tuple-of-trivially-converting-types */) : AdcValueHolder(std::forward(getter), std::forward(setter), std::forward(validator)) { // setup trivially-defined conversion function AdcValueHolder::setupTrivialConvertFunc, std::tuple>(); } template AdcValueHolder(std::invocable<> auto&& getter, std::invocable&> auto&& setter, const std::tuple& t /* tuple-of-trivially-converting-types */) : AdcValueHolder(std::forward(getter), std::forward(setter), AdcValueHolder::AdcValueHolderDummyValidator>, t) { } AdcValueHolder(const AdcValueHolder&) = default; AdcValueHolder(AdcValueHolder&&) = default; virtual ~AdcValueHolder() = default; /* PUBLIC METHODS */ template , typename VT = decltype(AdcValueHolder::AdcValueHolderDummyValidator)> AdcValueHolder& resetValueHolder(GT&& getter, std::invocable auto&& setter, VT&& validator = AdcValueHolder::AdcValueHolderDummyValidator) requires std::invocable && std::predicate { init(std::forward(getter), std::forward(setter), std::forward(validator)); return *this; } template AdcValueHolder& resetValueHolder(std::invocable<> auto&& getter, std::invocable&> auto&& setter, std::predicate&> auto&& validator, const std::tuple& /* tuple-of-trivially-converting-types */) { resetValueHolder(std::forward(getter), std::forward(setter), std::forward(validator)); // setup trivially-defined conversion function AdcValueHolder::setupTrivialConvertFunc, std::tuple>(); return *this; } template AdcValueHolder& resetValueHolder(std::invocable<> auto&& getter, std::invocable&> auto&& setter, const std::tuple& t /* tuple-of-trivially-converting-types */) { return resetValueHolder(std::forward(getter), std::forward(setter), AdcValueHolder::AdcValueHolderDummyValidator>, t); } template AdcValueHolder& addConvertFunc(FromFuncT&& func_from_internal, ToFuncT&& func_to_internal) requires std::invocable>> && std::invocable>> { using from_sig_t = typename traits::adc_func_traits; using to_sig_t = typename traits::adc_func_traits; // using value_t = typename to_sig_t::ret_t; // internal value type using value_t = std::remove_cv_t; // internal value type // using user_t = typename from_sig_t::ret_t; using user_t = std::remove_cv_t; // static_assert(!std::is_same_v, "void IS NOT VALID TYPE!!!"); // static_assert(!std::is_void_v::arg1_t>, // "INVALID CONVERSIONAL FUNCTION!!!"); // static_assert(std::is_same_v::arg1_t>, // value_t>, // "INVALID CONVERSIONAL FUNCTION!!!"); _getterFunc[this] = [wrapper = traits::adc_pf_wrapper(std::forward(func_from_internal)), this]() { auto& getter = _getterFunc[this]; if (getter) { auto val = getter(); return std::get<0>(wrapper)(val); // convert from internal type } // invalid conversion function signature throw std::system_error(AdcValueHolderErrorCode::ERROR_INTERNAL_TYPE_MISMATCH); }; _setterFunc[this] = [wrapper = traits::adc_pf_wrapper(std::forward(func_to_internal)), this](const user_t& val) { value_t value = std::get<0>(wrapper)(val); // convert to internal type auto& setter = _setterFunc[this]; if (setter) { setter(value); } else { // invalid conversion function signature throw std::system_error(AdcValueHolderErrorCode::ERROR_INTERNAL_TYPE_MISMATCH); } }; return *this; } template operator UT() { using v_t = std::remove_reference_t; using val_t = std::conditional_t, std::add_pointer_t>, v_t>; auto getter = _getterFunc[this]; if (getter) { return getter(); } throw std::system_error(AdcValueHolderErrorCode::ERROR_NO_CONV_FUNC); } template AdcValueHolder& operator=(UT&& value) { // using v_t = std::remove_reference_t; // using v_t = std::remove_cvref_t; // using val_t = std::conditional_t, std::add_pointer_t>, v_t>; using val_t = std::decay_t; auto setter = _setterFunc[this]; if (setter) { // setter(std::forward(value)); setter(value); } else { throw std::system_error(AdcValueHolderErrorCode::ERROR_NO_CONV_FUNC); } return *this; } AdcValueHolder& operator=(AdcValueHolder&& other) = default; AdcValueHolder& operator=(const AdcValueHolder& other) = default; protected: /* STATIC HELPER METHODS */ template void setupTrivialConvertFuncImpl() { if constexpr (I < std::tuple_size_v) { using elem_t = std::tuple_element_t; if constexpr (!std::is_same_v) { addConvertFunc([](const VT& v) { return static_cast(v); }, [](const elem_t& v) { return static_cast(v); }); } AdcValueHolder::setupTrivialConvertFuncImpl(); } } template void setupTrivialConvertFunc() { setupTrivialConvertFuncImpl(); } }; /* factory functions */ template , typename VT = decltype(AdcValueHolder::AdcValueHolderDummyValidator)> AdcValueHolder make_arith_valueholder(GT&& getter, std::invocable auto&& setter, VT&& validator = AdcValueHolder::AdcValueHolderDummyValidator) requires std::invocable && std::predicate { using val_t = traits::adc_retval_t; // static_assert(std::predicate&>, // "INVALID VALIDATOR TYPE!!!"); static_assert(std::is_arithmetic_v, "GETTER MUST RETURN AN ARITHMETIC TYPE VALUE!!!"); return AdcValueHolder(std::forward(getter), std::forward(setter), std::forward(validator), AdcValueHolder::_defaultTrivialConvTypes); } /* */ template class AdcSerializingValueHolder : public AdcValueHolder { protected: std::function _serializerWrapper = []() { }; std::function _deserializerWrapper; template void init(GT&& getter, ST&& setter, VT&& validator, SRT&& serializer, DSRT&& deserializer) { _serializerWrapper = [wrapper = traits::adc_pf_wrapper(std::forward(getter), std::forward(serializer))]() { auto& getter = std::get<0>(wrapper); auto& serializer = std::get<1>(wrapper); auto val = getter(); return serializer(val); }; using v_t = traits::adc_retval_t; _serializerWrapper = [wrapper = traits::adc_pf_wrapper(std::forward(setter), std::forward(validator), std::forward(deserializer))](const SerializedT& sval) { auto& setter = std::get<0>(wrapper); auto& validator = std::get<1>(wrapper); auto& deserializer = std::get<2>(wrapper); v_t val = deserializer(sval); if (validator(val)) { setter(val); } else { throw std::system_error(AdcValueHolderErrorCode::ERROR_VALUE_IS_NOT_VALID); } }; } public: using AdcValueHolder::AdcValueHolder; virtual ~AdcSerializingValueHolder() = default; }; } // namespace adc