#pragma once /* ABSTRACT DEVICE COMPONENTS LIBRARY */ #include #include #include "adc_traits.h" #include "adc_utils.h" namespace adc { // error codes enum class AdcValueHolderErrorCode : int { ERROR_OK, ERROR_NO_CONV_FUNC, ERROR_INTERNAL_TYPE_MISMATCH }; enum class AdcSerializingValueHolderErrorCode : int { ERROR_OK, ERROR_INVALID_SERIALIZED_TYPE }; } // namespace adc namespace std { template <> class is_error_code_enum : public true_type { }; 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 "ADC_VALUE_HOLDER_CATEGORY"; } 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)"; default: return "UNKNOWN"; } } static const AdcValueHolderErrorCategory& get() { static const AdcValueHolderErrorCategory constInst; return constInst; } }; struct AdcSerializingValueHolderErrorCategory : public std::error_category { AdcSerializingValueHolderErrorCategory() : std::error_category() {} const char* name() const noexcept { return "ADC_SERIALIZING_VALUE_HOLDER_CATEGORY"; } std::string message(int ec) const { AdcSerializingValueHolderErrorCode err = static_cast(ec); switch (err) { case AdcSerializingValueHolderErrorCode::ERROR_OK: return "OK"; case AdcSerializingValueHolderErrorCode::ERROR_INVALID_SERIALIZED_TYPE: return "invalid user-passed serialized type"; default: return "UNKNOWN"; } } static const AdcSerializingValueHolderErrorCategory& get() { static const AdcSerializingValueHolderErrorCategory constInst; return constInst; } }; inline std::error_code make_error_code(AdcValueHolderErrorCode ec) { return std::error_code(static_cast(ec), AdcValueHolderErrorCategory::get()); } inline std::error_code make_error_code(AdcSerializingValueHolderErrorCode ec) { return std::error_code(static_cast(ec), AdcSerializingValueHolderErrorCategory::get()); } /* GENERAL-PURPOSE VALUE HOLDER CLASS */ class AdcValueHolder { protected: template using ret_value_t = std::decay_t>; template inline static std::unordered_map> _getterFunc{}; template inline static std::unordered_map> _setterFunc{}; std::function _clearFunc; std::function _copyFunc; std::function _moveFunc; public: // default trivial types (just arithmetic ones) constexpr static std::tuple defaultTrivialConvTypes{}; /* CONSTRUCTORS AND DESTRUCTOR */ template GT, typename ValueT = ret_value_t, std::invocable ST> AdcValueHolder(GT&& getter, ST&& setter) { _getterFunc.emplace(this, std::forward(getter)); _setterFunc.emplace(this, std::forward(setter)); _clearFunc = [this]() { _getterFunc.erase(this); _setterFunc.erase(this); }; // copy TO other _copyFunc = [this](AdcValueHolder* other) { _getterFunc.emplace(other, _getterFunc[this]); _setterFunc.emplace(other, _setterFunc[this]); }; // move TO other _moveFunc = [this](AdcValueHolder* other) { _getterFunc.emplace(other, std::move(_getterFunc[this])); _setterFunc.emplace(other, std::move(_setterFunc[this])); }; } template TupleT, std::invocable<> GT, typename ValueT = ret_value_t, std::invocable ST> AdcValueHolder(TupleT&&, GT&& getter, ST&& setter) : AdcValueHolder(std::forward(getter), std::forward(setter)) { // setup trivially-defined conversion function AdcValueHolder::setupTrivialConvertFunc>(); } AdcValueHolder(const AdcValueHolder& other) { _clearFunc(); other._copyFunc(this); _clearFunc = other._clearFunc; _copyFunc = other._copyFunc; _moveFunc = other._moveFunc; }; AdcValueHolder(AdcValueHolder&& other) { _clearFunc(); other._moveFunc(this); _clearFunc = std::move(other._clearFunc); _copyFunc = std::move(other._copyFunc); _moveFunc = std::move(other._moveFunc); }; virtual ~AdcValueHolder() { _clearFunc(); }; /* PUBLIC METHODS */ template AdcValueHolder& addConvertFunc(FromFuncT&& func_from_internal, ToFuncT&& func_to_internal) requires std::invocable&> && std::invocable&> { using value_t = ret_value_t; // it must be internal value type using user_t = ret_value_t; _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); } }; _clearFunc = [prev_clear = _clearFunc, this]() { prev_clear(); _getterFunc.erase(this); _setterFunc.erase(this); }; _copyFunc = [prev_copy = _copyFunc, this](AdcValueHolder* other) { prev_copy(other); _getterFunc.emplace(other, _getterFunc[this]); _setterFunc.emplace(other, _setterFunc[this]); }; // move TO other _moveFunc = [prev_move = _moveFunc, this](AdcValueHolder* other) { prev_move(other); _getterFunc.emplace(other, std::move(_getterFunc[this])); _setterFunc.emplace(other, std::move(_setterFunc[this])); }; return *this; } template operator UT() const { using val_t = std::decay_t; auto getter = _getterFunc[this]; if (getter) { return getter(); } throw std::system_error(AdcValueHolderErrorCode::ERROR_NO_CONV_FUNC); } template AdcValueHolder& operator=(UT&& value) { 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) { if (&other != this) { _clearFunc(); other._moveFunc(this); _clearFunc = std::move(other._clearFunc); _copyFunc = std::move(other._copyFunc); _moveFunc = std::move(other._moveFunc); } return *this; } AdcValueHolder& operator=(const AdcValueHolder& other) { if (&other != this) { _clearFunc(); other._copyFunc(this); _clearFunc = other._clearFunc; _copyFunc = other._copyFunc; _moveFunc = other._moveFunc; } return *this; } protected: 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); }); } setupTrivialConvertFuncImpl(); } } template void setupTrivialConvertFunc() { setupTrivialConvertFuncImpl(); } }; class AdcSerializingValueHolder : public AdcValueHolder { protected: template inline static std::unordered_map> _serializerFunc{}; template inline static std::unordered_map> _deserializerFunc{}; // shadow base class's members std::function _clearFunc; std::function _copyFunc; std::function _moveFunc; public: template < std::invocable<> GT, typename ValueT = ret_value_t, std::invocable ST, std::invocable SRT = decltype(utils::AdcDefaultValueConverter<>::serialize), typename SerializedT = ret_value_t, std::invocable DSRT = decltype(utils::AdcDefaultValueConverter<>::deserialize)> AdcSerializingValueHolder(GT&& getter, ST&& setter, SRT&& serializer = utils::AdcDefaultValueConverter<>::serialize, DSRT&& deserializer = utils::AdcDefaultValueConverter<>::deserialize) : AdcValueHolder(std::forward(getter), std::forward(setter)) { _serializerFunc[this] = [wrapper = traits::adc_pf_wrapper(std::forward(serializer)), this]() { auto& serializer = std::get<0>(wrapper); auto val = _getterFunc[this](); return serializer(val); }; _deserializerFunc[this] = [wrapper = traits::adc_pf_wrapper(std::forward(deserializer)), this](const SerializedT& sval) { auto& deserializer = std::get<0>(wrapper); ValueT val = deserializer(sval); _setterFunc[this](val); }; _clearFunc = [this]() { _serializerFunc.erase(this); _deserializerFunc.erase(this); }; _copyFunc = [this](AdcSerializingValueHolder* other) { _serializerFunc.emplace(other, _serializerFunc[this]); _deserializerFunc.emplace(other, _deserializerFunc[this]); }; _moveFunc = [this](AdcSerializingValueHolder* other) { _serializerFunc.emplace(other, std::move(_serializerFunc[this])); _deserializerFunc.emplace(other, std::move(_deserializerFunc[this])); }; } template < traits::adc_tuple_like<> TupleT, std::invocable<> GT, typename ValueT = ret_value_t, std::invocable ST, std::invocable SRT = decltype(utils::AdcDefaultValueConverter<>::serialize), typename SerializedT = ret_value_t, std::invocable DSRT = decltype(utils::AdcDefaultValueConverter<>::deserialize)> AdcSerializingValueHolder(TupleT&&, GT&& getter, ST&& setter, SRT&& serializer = utils::AdcDefaultValueConverter<>::serialize, DSRT&& deserializer = utils::AdcDefaultValueConverter<>::deserialize) : AdcSerializingValueHolder(std::forward(getter), std::forward(setter), std::forward(serializer), std::forward(deserializer)) { AdcValueHolder::setupTrivialConvertFunc>(); } virtual ~AdcSerializingValueHolder() { _clearFunc(); }; AdcSerializingValueHolder(const AdcSerializingValueHolder& other) : AdcValueHolder(other) { _clearFunc(); _copyFunc(other); } AdcSerializingValueHolder(AdcSerializingValueHolder&& other) : AdcValueHolder(std::move(other)) { _clearFunc(); _moveFunc(other); } AdcSerializingValueHolder& operator=(const AdcSerializingValueHolder& other) { AdcValueHolder::operator=(other); _copyFunc(other); return *this; } AdcSerializingValueHolder& operator=(AdcSerializingValueHolder&& other) { AdcValueHolder::operator=(std::move(other)); _moveFunc(other); return *this; } using AdcValueHolder::operator=; template SerializedT serialize() { using s_t = std::decay_t; auto& serializer = _serializerFunc[this]; if (serializer) { return serializer(); } throw std::system_error(AdcSerializingValueHolderErrorCode::ERROR_INVALID_SERIALIZED_TYPE); } template void deserialize(const SerializedT& sval) { using s_t = std::decay_t; auto& deserializer = _deserializerFunc[this]; if (deserializer) { deserializer(sval); } else { throw std::system_error(AdcSerializingValueHolderErrorCode::ERROR_INVALID_SERIALIZED_TYPE); } } }; /* factory functions */ template HolderT makeArithmValue(Ts&&... ctor_args) { static_assert(std::is_same_v || std::is_same_v, "Invalid value holder type!!!"); return HolderT(AdcValueHolder::defaultTrivialConvTypes, std::forward(ctor_args)...); } } // namespace adc