198 lines
4.8 KiB
C++
198 lines
4.8 KiB
C++
#pragma once
|
|
|
|
#include <algorithm>
|
|
#include <memory>
|
|
#include <ranges>
|
|
#include <system_error>
|
|
#include <unordered_map>
|
|
|
|
#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<adc::AdcGenericDeviceErrorCode> : 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<AdcGenericDeviceErrorCode>(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<int>(ec), AdcGenericDeviceErrorCategory::get());
|
|
}
|
|
|
|
|
|
|
|
template <typename IdentT, interfaces::adc_device_attr_c AttributeT, interfaces::adc_device_cmd_c CommandT>
|
|
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->second();
|
|
it->second->operator()();
|
|
} 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;
|
|
return *(it->second);
|
|
}
|
|
|
|
throw std::system_error(AdcGenericDeviceErrorCode::ERROR_ATTR_IDENT);
|
|
}
|
|
|
|
|
|
AdcGenericDevice& addCommand(CommandT&& cmd)
|
|
{
|
|
// _deviceCommands.insert({cmd.ident(), std::move(cmd)});
|
|
_deviceCommands.insert({cmd.ident(), std::make_unique<CommandT>(std::move(cmd))});
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
template <typename... CtorArgTs>
|
|
AdcGenericDevice& addCommand(CtorArgTs&&... ctor_args)
|
|
{
|
|
return addCommand({std::forward<CtorArgTs>(ctor_args)...});
|
|
}
|
|
|
|
AdcGenericDevice& delCommand(const cmd_ident_t& cmd_ident)
|
|
{
|
|
_deviceCommands.erase(cmd_ident);
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
AdcGenericDevice& addAttribute(AttributeT&& attr)
|
|
{
|
|
// _deviceAttributes.insert({attr.ident(), std::move(attr)});
|
|
_deviceAttributes.insert({attr.ident(), std::make_unique<AttributeT>(std::move(attr))});
|
|
|
|
return *this;
|
|
}
|
|
|
|
template <typename... CtorArgTs>
|
|
AdcGenericDevice& addAttribute(CtorArgTs&&... ctor_args)
|
|
{
|
|
return addAttribute(AttributeT(std::forward<CtorArgTs>(ctor_args)...));
|
|
}
|
|
|
|
|
|
AdcGenericDevice& delAttribute(const attr_ident_t& attr_ident)
|
|
{
|
|
_deviceAttributes.erase(attr_ident);
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
template <std::ranges::output_range<cmd_ident_t> ResultT>
|
|
AdcGenericDevice& commandIdents(ResultT& idents)
|
|
{
|
|
std::ranges::copy(_deviceCommands | std::views::keys, std::back_inserter(idents));
|
|
|
|
return *this;
|
|
}
|
|
|
|
template <std::ranges::output_range<attr_ident_t> ResultT>
|
|
AdcGenericDevice& attributeIdents(ResultT& idents)
|
|
{
|
|
std::ranges::copy(_deviceAttributes | std::views::keys, std::back_inserter(idents));
|
|
|
|
return *this;
|
|
}
|
|
|
|
protected:
|
|
IdentT _ident;
|
|
|
|
// std::unordered_map<attr_ident_t, AttributeT> _deviceAttributes;
|
|
// std::unordered_map<cmd_ident_t, CommandT> _deviceCommands;
|
|
std::unordered_map<attr_ident_t, std::unique_ptr<AttributeT>> _deviceAttributes;
|
|
std::unordered_map<cmd_ident_t, std::unique_ptr<CommandT>> _deviceCommands;
|
|
};
|
|
|
|
} // namespace adc
|