#pragma once #include #include #include #include #include "adc_device_concepts.h" namespace adc { // error codes enum class AdcGenericDeviceErrorCode : int { ERROR_OK, ERROR_ATTR_IDENT, ERROR_COMMAND_IDENT, ERROR_UNKNOWN }; } // namespace adc namespace std { template <> class is_error_code_enum : public true_type { }; } // namespace std namespace adc { // error category struct AdcGenericDeviceErrorCategory : public std::error_category { AdcGenericDeviceErrorCategory() : std::error_category() {} const char* name() const noexcept { return "ADC_GENERIC_DEVICE"; } std::string message(int ec) const { AdcGenericDeviceErrorCode err = static_cast(ec); switch (err) { case AdcGenericDeviceErrorCode::ERROR_OK: return "OK"; case AdcGenericDeviceErrorCode::ERROR_ATTR_IDENT: return "invalid attribute identificator"; case AdcGenericDeviceErrorCode::ERROR_COMMAND_IDENT: return "invalid command identificator"; default: return "UNKNOWN"; } } static const AdcGenericDeviceErrorCategory& get() { static const AdcGenericDeviceErrorCategory constInst; return constInst; } }; inline std::error_code make_error_code(AdcGenericDeviceErrorCode ec) { return std::error_code(static_cast(ec), AdcGenericDeviceErrorCategory::get()); } template class AdcGenericDevice { public: typedef IdentT ident_t; typedef AttributeT attribute_t; typedef CommandT command_t; using attr_ident_t = typename AttributeT::ident_t; using cmd_ident_t = typename CommandT::ident_t; /* CONSTRUCTORS AND DESTRUCTOR */ AdcGenericDevice(const IdentT& ident) : _ident(ident) {} virtual ~AdcGenericDevice() = default; /* PUBLIC METHODS */ IdentT ident() const { return _ident; } AdcGenericDevice& operator()(const cmd_ident_t& cmd_ident) { auto it = _deviceCommands.find(cmd_ident); if (it != _deviceCommands.end()) { *it(); } else { throw std::system_error(AdcGenericDeviceErrorCode::ERROR_COMMAND_IDENT); } return *this; } AttributeT& operator[](const attr_ident_t& attr_ident) { auto it = _deviceAttributes.find(attr_ident); if (it != _deviceAttributes.end()) { return it->second; } throw std::system_error(AdcGenericDeviceErrorCode::ERROR_ATTR_IDENT); } AdcGenericDevice& addCommand(CommandT&& cmd) { auto id = cmd.ident(); _deviceCommands.emplace(id, std::move(cmd)); return *this; } AdcGenericDevice& delCommand(const cmd_ident_t& cmd_ident) { _deviceCommands.erase(cmd_ident); return *this; } AdcGenericDevice& addAttribute(AttributeT&& attr) { auto id = attr.ident(); _deviceAttributes.emplace(id, std::move(attr)); return *this; } template AdcGenericDevice& addAttribute(CtorArgTs&&... ctor_args) { return addAttribute(AttributeT{std::forward(ctor_args)...}); } AdcGenericDevice& delAttribute(const attr_ident_t& attr_ident) { _deviceAttributes.erase(attr_ident); return *this; } template ResultT> AdcGenericDevice& commandIdents(ResultT& idents) { std::ranges::copy(_deviceCommands | std::views::keys, std::back_inserter(idents)); return *this; } template ResultT> AdcGenericDevice& attributeIdents(ResultT& idents) { std::ranges::copy(_deviceAttributes | std::views::keys, std::back_inserter(idents)); return *this; } protected: IdentT _ident; std::map _deviceAttributes; std::map _deviceCommands; }; } // namespace adc