...
This commit is contained in:
@@ -15,7 +15,9 @@ namespace constants
|
||||
static constexpr char ADC_DEFAULT_KEY_VALUE_DELIMITER1[] = " ";
|
||||
static constexpr char ADC_DEFAULT_KEY_PARAM_DELIMITER[] = " ";
|
||||
static constexpr char ADC_DEFAULT_PARAM_PARAM_DELIMITER[] = " ";
|
||||
static constexpr char ADC_DEFAULT_VALUE_DELIMITER[] = " ";
|
||||
static constexpr char ADC_DEFAULT_COMPOSITE_PARAM_DELIMITER[] = ",";
|
||||
static constexpr char ADC_DEFAULT_COMPOSITE_VALUE_DELIMITER[] = ",";
|
||||
|
||||
} // namespace constants
|
||||
|
||||
@@ -23,16 +25,32 @@ static constexpr char ADC_DEFAULT_COMPOSITE_PARAM_DELIMITER[] = ",";
|
||||
|
||||
template <traits::adc_char_range ByteSeqT,
|
||||
const char KEY_VALUE_DELIM[] = constants::ADC_DEFAULT_KEY_VALUE_DELIMITER1,
|
||||
const char VALUE_DELIM[] = constants::ADC_DEFAULT_COMPOSITE_PARAM_DELIMITER>
|
||||
class AdcKeyValueMessage1
|
||||
const char VALUE_DELIM[] = constants::ADC_DEFAULT_VALUE_DELIMITER,
|
||||
const char COMPOSITE_VALUE_DELIM[] = constants::ADC_DEFAULT_COMPOSITE_VALUE_DELIMITER>
|
||||
class AdcKeyValueMessage
|
||||
{
|
||||
public:
|
||||
static constexpr std::span keyValueDelimiter{KEY_VALUE_DELIM, utils::AdcCharArrSize(KEY_VALUE_DELIM)};
|
||||
static constexpr std::span valueDelimiter{VALUE_DELIM, utils::AdcCharArrSize(VALUE_DELIM)};
|
||||
static constexpr size_t keyValueDelimiterSize = utils::AdcCharArrSize(KEY_VALUE_DELIM);
|
||||
static constexpr std::span keyValueDelimiter{KEY_VALUE_DELIM, keyValueDelimiterSize};
|
||||
|
||||
AdcKeyValueMessage1(ByteSeqT& byte_seq) : _byteSequence(byte_seq) {}
|
||||
static constexpr size_t valueDelimiterSize = utils::AdcCharArrSize(VALUE_DELIM);
|
||||
static constexpr std::span valueDelimiter{VALUE_DELIM, valueDelimiterSize};
|
||||
|
||||
virtual ~AdcKeyValueMessage1() = default;
|
||||
static constexpr size_t compValueDelimiterSize = utils::AdcCharArrSize(COMPOSITE_VALUE_DELIM);
|
||||
static constexpr std::span compValueDelimiter{COMPOSITE_VALUE_DELIM, compValueDelimiterSize};
|
||||
|
||||
static_assert(keyValueDelimiterSize && valueDelimiterSize && compValueDelimiterSize,
|
||||
"KEY-VALUE, VALUE-PARTS AND COMPOSITE-VALUE DELIMITERS MUST NOT BE AN EMPTY ARRAY!!!");
|
||||
|
||||
AdcKeyValueMessage(ByteSeqT& byte_seq) : _byteSequence(byte_seq) {}
|
||||
|
||||
virtual ~AdcKeyValueMessage() = default;
|
||||
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return std::ranges::size(_byteSequence) == 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires(traits::adc_char_view<T> && std::ranges::contiguous_range<ByteSeqT>) ||
|
||||
@@ -111,39 +129,132 @@ public:
|
||||
}
|
||||
|
||||
|
||||
template <typename KeyT, typename ValueT>
|
||||
requires traits::adc_output_char_range<ByteSeqT>
|
||||
AdcKeyValueMessage1& setKeyValue(KeyT&& key, ValueT&& value)
|
||||
template <typename T>
|
||||
requires(std::ranges::contiguous_range<ByteSeqT> && traits::adc_char_view<std::ranges::range_value_t<T>>) ||
|
||||
traits::adc_range_of_output_char_range<T>
|
||||
auto valueParts(size_t start = 0, size_t N = std::numeric_limits<size_t>::max()) const
|
||||
{
|
||||
if (std::ranges::size(_byteSequence)) {
|
||||
_byteSequence = _byteSequence();
|
||||
auto val = value<std::ranges::range_value_t<T>>();
|
||||
|
||||
return utils::AdcSplitCharRange<T>(val, valueDelimiter, start, N);
|
||||
}
|
||||
|
||||
auto valueParts(size_t start = 0, size_t N = std::numeric_limits<size_t>::max()) const
|
||||
{
|
||||
if constexpr (std::ranges::contiguous_range<ByteSeqT>) {
|
||||
return valueParts<std::vector<std::string_view>>(start, N);
|
||||
} else {
|
||||
return valueParts<std::vector<std::string>>(start, N);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
requires traits::adc_output_char_range<T> || traits::adc_char_view<T>
|
||||
auto joinValueParts(size_t start = 0, size_t N = std::numeric_limits<size_t>::max()) const
|
||||
{
|
||||
T res;
|
||||
|
||||
if constexpr (std::ranges::contiguous_range<ByteSeqT>) {
|
||||
auto pp = valueParts<std::vector<std::span<const char>>>(start, N);
|
||||
if (pp.size()) {
|
||||
res = T{pp.front().begin(), pp.back().end()};
|
||||
}
|
||||
} else {
|
||||
utils::AdcJoinRange(valueParts<std::vector<std::vector<const char>>>(start, N), valueDelimiter, res);
|
||||
}
|
||||
|
||||
std::ranges::copy(
|
||||
utils::AdcDefaultValueConverter<KEY_VALUE_DELIM>::template serialize<ByteSeqT>(std::forward<KeyT>(key)),
|
||||
std::back_inserter(_byteSequence));
|
||||
return res;
|
||||
}
|
||||
|
||||
std::ranges::copy(keyValueDelimiter, std::back_inserter(_byteSequence));
|
||||
|
||||
std::ranges::copy(
|
||||
utils::AdcDefaultValueConverter<KEY_VALUE_DELIM>::template serialize(std::forward<ValueT>(value)),
|
||||
std::back_inserter(_byteSequence));
|
||||
auto joinValueParts(size_t start = 0, size_t N = std::numeric_limits<size_t>::max()) const
|
||||
{
|
||||
if constexpr (std::ranges::contiguous_range<ByteSeqT>) {
|
||||
return joinValueParts<std::string_view>(start, N);
|
||||
} else {
|
||||
return joinValueParts<std::string>(start, N);
|
||||
}
|
||||
}
|
||||
|
||||
// template <typename KeyT, typename ValueT>
|
||||
// requires traits::adc_output_char_range<ByteSeqT>
|
||||
// AdcKeyValueMessage& setKeyValue(KeyT&& key, ValueT&& value)
|
||||
// {
|
||||
// if (std::ranges::size(_byteSequence)) {
|
||||
// _byteSequence = ByteSeqT();
|
||||
// }
|
||||
|
||||
// std::ranges::copy(
|
||||
// utils::AdcDefaultValueConverter<VALUE_DELIM>::template serialize<ByteSeqT>(std::forward<KeyT>(key)),
|
||||
// std::back_inserter(_byteSequence));
|
||||
|
||||
// std::ranges::copy(keyValueDelimiter, std::back_inserter(_byteSequence));
|
||||
|
||||
// std::ranges::copy(
|
||||
// utils::AdcDefaultValueConverter<VALUE_DELIM>::template serialize<ByteSeqT>(std::forward<ValueT>(value)),
|
||||
// std::back_inserter(_byteSequence));
|
||||
|
||||
// return *this;
|
||||
// }
|
||||
|
||||
|
||||
// template <typename ValueT>
|
||||
// AdcKeyValueMessage& setValue(ValueT&& value)
|
||||
// requires traits::adc_output_char_range<ByteSeqT>
|
||||
// {
|
||||
// std::vector<char> kw;
|
||||
// std::ranges::copy(key<std::span<const char>>(), std::back_inserter(kw));
|
||||
|
||||
// return setKeyValue(kw, std::forward<ValueT>(value));
|
||||
// }
|
||||
|
||||
|
||||
template <typename KeyT, typename... ValuePartTs>
|
||||
requires traits::adc_output_char_range<ByteSeqT>
|
||||
AdcKeyValueMessage& setKeyValue(KeyT&& key, ValuePartTs&&... values)
|
||||
{
|
||||
if (std::ranges::size(_byteSequence)) {
|
||||
_byteSequence = ByteSeqT();
|
||||
}
|
||||
|
||||
std::ranges::copy(utils::AdcDefaultValueConverter<COMPOSITE_VALUE_DELIM>::template serialize<ByteSeqT>(
|
||||
std::forward<KeyT>(key)),
|
||||
std::back_inserter(_byteSequence));
|
||||
|
||||
if constexpr (sizeof...(ValuePartTs)) {
|
||||
std::ranges::copy(keyValueDelimiter, std::back_inserter(_byteSequence));
|
||||
setValueHelper(std::forward<ValuePartTs>(values)...);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template <typename ValueT>
|
||||
AdcKeyValueMessage1& setValue(ValueT&& value)
|
||||
template <typename... ValuePartTs>
|
||||
requires traits::adc_output_char_range<ByteSeqT>
|
||||
AdcKeyValueMessage& setValue(ValuePartTs&&... values)
|
||||
{
|
||||
std::vector<char> kw;
|
||||
std::ranges::copy(key<std::span<const char>>(), std::back_inserter(kw));
|
||||
|
||||
return setKeyValue(kw, std::forward<ValueT>(value));
|
||||
return setValue(kw, std::forward<ValuePartTs>(values)...);
|
||||
}
|
||||
|
||||
protected:
|
||||
ByteSeqT& _byteSequence;
|
||||
|
||||
template <typename ValuePartT, typename... ValuePartTs>
|
||||
void setValueHelper(ValuePartT&& value, ValuePartTs&&... values)
|
||||
{
|
||||
std::ranges::copy(utils::AdcDefaultValueConverter<COMPOSITE_VALUE_DELIM>::template serialize<ByteSeqT>(
|
||||
std::forward<ValuePartT>(value)),
|
||||
std::back_inserter(_byteSequence));
|
||||
|
||||
if constexpr (sizeof...(ValuePartTs)) {
|
||||
std::ranges::copy(valueDelimiter, std::back_inserter(_byteSequence));
|
||||
setValueHelper(std::forward<ValuePartTs>(values)...);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -152,9 +263,9 @@ template <traits::adc_char_range ByteSeqT,
|
||||
const char* KEY_PARAM_DELIM = constants::ADC_DEFAULT_KEY_PARAM_DELIMITER,
|
||||
const char* PARAM_PARAM_DELIM = constants::ADC_DEFAULT_PARAM_PARAM_DELIMITER,
|
||||
const char* COMPOSITE_PARAM_DELIM = constants::ADC_DEFAULT_COMPOSITE_PARAM_DELIMITER>
|
||||
class AdcDeviceNetMessage : public AdcKeyValueMessage1<ByteSeqT, KEY_PARAM_DELIM, COMPOSITE_PARAM_DELIM>
|
||||
class AdcDeviceNetMessage : public AdcKeyValueMessage<ByteSeqT, KEY_PARAM_DELIM, COMPOSITE_PARAM_DELIM>
|
||||
{
|
||||
using base_t = AdcKeyValueMessage1<ByteSeqT, KEY_PARAM_DELIM, COMPOSITE_PARAM_DELIM>;
|
||||
using base_t = AdcKeyValueMessage<ByteSeqT, KEY_PARAM_DELIM, COMPOSITE_PARAM_DELIM>;
|
||||
|
||||
public:
|
||||
static constexpr std::span keyParamDelimiter{KEY_PARAM_DELIM, utils::AdcCharArrSize(KEY_PARAM_DELIM)};
|
||||
@@ -166,63 +277,275 @@ public:
|
||||
|
||||
AdcDeviceNetMessage(ByteSeqT& byte_seq) : base_t(byte_seq) {}
|
||||
|
||||
template <traits::adc_char_view VT>
|
||||
VT keyword() const
|
||||
{
|
||||
std::span<const char> key;
|
||||
// first, remove spaces at the beginning and end of byte sequence
|
||||
auto bs = utils::AdcTrimSpacesView<std::span<const char>>(this->_byteSequence);
|
||||
virtual ~AdcDeviceNetMessage() = default;
|
||||
|
||||
auto found = std::ranges::search(bs, keyParamDelimiter);
|
||||
if (found.empty()) { // only keyword
|
||||
return VT(bs.begin(), bs.end());
|
||||
template <typename T>
|
||||
requires(std::ranges::contiguous_range<ByteSeqT> && traits::adc_char_view<std::ranges::range_value_t<T>>) ||
|
||||
traits::adc_range_of_output_char_range<T>
|
||||
auto params(size_t start = 0, size_t N = std::numeric_limits<size_t>::max()) const
|
||||
{
|
||||
auto val = base_t::template value<std::ranges::range_value_t<T>>();
|
||||
|
||||
return utils::AdcSplitCharRange<T>(val, paramParamDelimiter, start, N);
|
||||
}
|
||||
|
||||
auto params(size_t start = 0, size_t N = std::numeric_limits<size_t>::max()) const
|
||||
{
|
||||
if constexpr (std::ranges::contiguous_range<ByteSeqT>) {
|
||||
return params<std::vector<std::string_view>>(start, N);
|
||||
} else {
|
||||
return params<std::vector<std::string>>(start, N);
|
||||
}
|
||||
|
||||
key = std::span(bs.begin(), found.begin());
|
||||
|
||||
|
||||
return utils::AdcTrimSpacesView<VT>(key);
|
||||
}
|
||||
|
||||
auto keyword() const
|
||||
{
|
||||
return keyword<std::string_view>();
|
||||
}
|
||||
|
||||
|
||||
template <traits::adc_range_of_view_char_range R>
|
||||
auto params(size_t start = 0, size_t N = std::numeric_limits<size_t>::max()) const
|
||||
template <typename T>
|
||||
requires traits::adc_output_char_range<T> || traits::adc_char_view<T>
|
||||
auto joinParams(size_t start = 0, size_t N = std::numeric_limits<size_t>::max()) const
|
||||
{
|
||||
auto val = base_t::template value<std::ranges::range_value_t<R>>();
|
||||
T res;
|
||||
|
||||
// R res;
|
||||
// std::ranges::for_each(std::views::split(val, keyParamDelimiter) | std::views::drop(start) |
|
||||
// std::views::take(N),
|
||||
// [&res](const auto& el) {
|
||||
// // remove spaces
|
||||
// std::back_inserter(res) =
|
||||
// utils::AdcTrimSpacesView<std::ranges::range_value_t<R>>(el);
|
||||
// // std::ranges::copy(utils::AdcTrimSpaces(el), std::back_inserter(res));
|
||||
// });
|
||||
|
||||
// return res;
|
||||
return utils::AdcSplitCharRange<R>(val, paramParamDelimiter, start, N);
|
||||
}
|
||||
|
||||
auto params(size_t start = 0, size_t N = std::numeric_limits<size_t>::max()) const
|
||||
{
|
||||
return params<std::vector<std::string_view>>(start, N);
|
||||
}
|
||||
|
||||
|
||||
template <traits::adc_output_char_range R>
|
||||
auto joinParams(size_t start = 0, size_t N = std::numeric_limits<size_t>::max())
|
||||
{
|
||||
R res;
|
||||
utils::AdcJoinRange(params<std::vector<std::span<const char>>>(start, N), paramParamDelimiter, res);
|
||||
if constexpr (std::ranges::contiguous_range<ByteSeqT>) {
|
||||
auto pp = params<std::vector<std::span<const char>>>(start, N);
|
||||
if (pp.size()) {
|
||||
res = T{pp.front().begin(), pp.back().end()};
|
||||
}
|
||||
} else {
|
||||
utils::AdcJoinRange(params<std::vector<std::vector<const char>>>(start, N), paramParamDelimiter, res);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
auto joinParams(size_t start = 0, size_t N = std::numeric_limits<size_t>::max()) const
|
||||
{
|
||||
if constexpr (std::ranges::contiguous_range<ByteSeqT>) {
|
||||
return joinParams<std::string_view>(start, N);
|
||||
} else {
|
||||
return joinParams<std::string>(start, N);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <traits::adc_input_char_range KeyT, typename... ParamTs>
|
||||
requires traits::adc_output_char_range<ByteSeqT>
|
||||
AdcDeviceNetMessage& setKeyParams(KeyT&& key, ParamTs&&... params)
|
||||
{
|
||||
this->setKeyValue(std::forward<KeyT>(key), std::string_view());
|
||||
|
||||
if constexpr (sizeof...(ParamTs)) {
|
||||
setParamsHelper(std::forward<ParamTs>(params)...);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
template <typename ParamT, typename... ParamTs>
|
||||
void setParamsHelper(ParamT&& param, ParamTs&&... params)
|
||||
{
|
||||
std::ranges::copy(utils::AdcDefaultValueConverter<COMPOSITE_PARAM_DELIM>::template serialize<ByteSeqT>(
|
||||
std::forward<ParamT>(param)),
|
||||
std::back_inserter(this->_byteSequence));
|
||||
|
||||
if constexpr (sizeof...(ParamTs)) {
|
||||
std::ranges::copy(paramParamDelimiter, std::back_inserter(this->_byteSequence));
|
||||
setParamsHelper(std::forward<ParamTs>(params)...);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <traits::adc_char_range ByteSeqT,
|
||||
const char KEY_VALUE_DELIM[] = constants::ADC_DEFAULT_KEY_VALUE_DELIMITER1,
|
||||
const char VALUE_DELIM[] = constants::ADC_DEFAULT_VALUE_DELIMITER,
|
||||
const char COMPOSITE_VALUE_DELIM[] = constants::ADC_DEFAULT_COMPOSITE_VALUE_DELIMITER>
|
||||
class AdcDeviceProtoMessage
|
||||
: protected AdcKeyValueMessage<ByteSeqT, KEY_VALUE_DELIM, VALUE_DELIM, COMPOSITE_VALUE_DELIM>
|
||||
{
|
||||
using base_t = AdcKeyValueMessage<ByteSeqT, KEY_VALUE_DELIM, VALUE_DELIM, COMPOSITE_VALUE_DELIM>;
|
||||
|
||||
public:
|
||||
static constexpr std::string_view ACK_KEY{"ACK"};
|
||||
static constexpr std::string_view SET_KEY{"SET"};
|
||||
static constexpr std::string_view GET_KEY{"GET"};
|
||||
static constexpr std::string_view CMD_KEY{"CMD"};
|
||||
static constexpr std::string_view ERR_KEY{"ERR"};
|
||||
static constexpr std::string_view HELLO_KEY{"HELLO"};
|
||||
static constexpr std::string_view DEVICE_KEY{"DEVICE"};
|
||||
static constexpr std::string_view NAMES_KEY{"NAMES"};
|
||||
|
||||
static constexpr std::array VALID_KEY{ACK_KEY, SET_KEY, GET_KEY, CMD_KEY,
|
||||
ERR_KEY, HELLO_KEY, DEVICE_KEY, NAMES_KEY};
|
||||
|
||||
|
||||
typedef std::array<size_t, VALID_KEY.size()> keyword_hash_array_t;
|
||||
|
||||
enum KEY_IDX : size_t {
|
||||
ACK_KEY_IDX,
|
||||
SET_KEY_IDX,
|
||||
GET_KEY_IDX,
|
||||
CMD_KEY_IDX,
|
||||
ERR_KEY_IDX,
|
||||
HELLO_KEY_IDX,
|
||||
DEVICE_KEY_IDX,
|
||||
NAMES_KEY_IDX
|
||||
};
|
||||
|
||||
private: // include here to allow clang compilation
|
||||
size_t _keyHash = 0;
|
||||
|
||||
template <size_t... I>
|
||||
static constexpr auto computeKeywordHashesImpl(std::index_sequence<I...>)
|
||||
{
|
||||
return keyword_hash_array_t{utils::AdcFNV1aHash(VALID_KEY[I])...};
|
||||
}
|
||||
template <typename Indices = std::make_index_sequence<VALID_KEY.size()>>
|
||||
static constexpr auto computeKeywordHashes()
|
||||
{
|
||||
return computeKeywordHashesImpl(Indices{});
|
||||
}
|
||||
|
||||
static constexpr keyword_hash_array_t KEY_HASHES = computeKeywordHashes();
|
||||
|
||||
auto keyHash()
|
||||
{
|
||||
return _keyHash = utils::AdcFNV1aHash(key());
|
||||
}
|
||||
|
||||
bool isKey(size_t idx) const
|
||||
{
|
||||
return _keyHash == KEY_HASHES[idx];
|
||||
}
|
||||
|
||||
public:
|
||||
AdcDeviceProtoMessage(ByteSeqT& byte_seq) : base_t(byte_seq)
|
||||
{
|
||||
keyHash();
|
||||
}
|
||||
|
||||
bool isValid() const
|
||||
{
|
||||
return std::ranges::any_of(KEY_HASHES, [this](size_t h) { return _keyHash == h; });
|
||||
}
|
||||
|
||||
bool isACK() const
|
||||
{
|
||||
return isKey(ACK_KEY_IDX);
|
||||
}
|
||||
|
||||
bool isSET() const
|
||||
{
|
||||
return isKey(SET_KEY_IDX);
|
||||
}
|
||||
|
||||
bool isGET() const
|
||||
{
|
||||
return isKey(GET_KEY_IDX);
|
||||
}
|
||||
|
||||
bool isCMD() const
|
||||
{
|
||||
return isKey(CMD_KEY_IDX);
|
||||
}
|
||||
|
||||
bool isERR() const
|
||||
{
|
||||
return isKey(ERR_KEY_IDX);
|
||||
}
|
||||
|
||||
bool isHELLO() const
|
||||
{
|
||||
return isKey(HELLO_KEY_IDX);
|
||||
}
|
||||
|
||||
bool isDEVICE() const
|
||||
{
|
||||
return isKey(DEVICE_KEY_IDX);
|
||||
}
|
||||
|
||||
bool isNAMES() const
|
||||
{
|
||||
return isKey(NAMES_KEY_IDX);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename T>
|
||||
requires(traits::adc_char_view<T> && std::ranges::contiguous_range<ByteSeqT>) ||
|
||||
traits::adc_output_char_range<T>
|
||||
auto key() const
|
||||
{
|
||||
return base_t::template key<T>();
|
||||
}
|
||||
|
||||
|
||||
auto key() const
|
||||
{
|
||||
return base_t::key();
|
||||
}
|
||||
|
||||
|
||||
void ack()
|
||||
{
|
||||
base_t::setKeyValue(ACK_KEY);
|
||||
|
||||
keyHash();
|
||||
}
|
||||
|
||||
template <traits::adc_input_char_range AttrNameT, typename ValueT, typename... ValueTs>
|
||||
void set(AttrNameT&& attr_name, ValueT&& value, ValueTs&&... values)
|
||||
{
|
||||
base_t::setKeyValue(SET_KEY, std::forward<AttrNameT>(attr_name), std::forward<ValueT>(value),
|
||||
std::forward<ValueTs>(values)...);
|
||||
|
||||
keyHash();
|
||||
}
|
||||
|
||||
template <traits::adc_input_char_range AttrNameT>
|
||||
void get(AttrNameT&& attr_name)
|
||||
{
|
||||
base_t::setKeyValue(GET_KEY, std::forward<AttrNameT>(attr_name));
|
||||
|
||||
keyHash();
|
||||
}
|
||||
|
||||
template <traits::adc_input_char_range CmdNameT>
|
||||
void cmd(CmdNameT&& cmd_name)
|
||||
{
|
||||
base_t::setKeyValue(CMD_KEY, std::forward<CmdNameT>(cmd_name));
|
||||
|
||||
keyHash();
|
||||
}
|
||||
|
||||
void err(const std::error_code& ec)
|
||||
{
|
||||
base_t::setKeyValue(ERR_KEY, ec.value(), ec.category(), ec.message());
|
||||
|
||||
keyHash();
|
||||
}
|
||||
|
||||
template <traits::adc_input_char_range SenderNameT, typename... ParamTs>
|
||||
void hello(SenderNameT&& name, ParamTs&&... params)
|
||||
{
|
||||
base_t::setKeyValue(HELLO_KEY, std::forward<SenderNameT>(name), std::forward<ParamTs>(params)...);
|
||||
|
||||
keyHash();
|
||||
}
|
||||
|
||||
template <traits::adc_input_char_range DevNameT>
|
||||
void device(DevNameT&& dev_name)
|
||||
{
|
||||
base_t::setKeyValue(DEVICE_KEY, std::forward<DevNameT>(dev_name));
|
||||
|
||||
keyHash();
|
||||
}
|
||||
|
||||
void names()
|
||||
{
|
||||
base_t::setKeyValue(NAMES_KEY);
|
||||
|
||||
keyHash();
|
||||
}
|
||||
};
|
||||
} // namespace adc
|
||||
|
||||
Reference in New Issue
Block a user