ADC/net/adc_device_netmsg.h
Timur A. Fatkhullin 8bcc8edbb0 ...
2024-10-06 23:12:22 +03:00

234 lines
7.6 KiB
C++

#pragma once
#include "../common/adc_utils.h"
// #include "adc_netmsg.h"
namespace adc
{
/* ABSTRACT DEVICE DEFAULT APPLICATION-LEVEL NETWORK PROTOCOL DEFINITIONS */
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_COMPOSITE_PARAM_DELIMITER[] = ",";
} // namespace constants
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
{
public:
static constexpr std::span keyValueDelimiter{KEY_VALUE_DELIM, sizeof(KEY_VALUE_DELIM) - 1};
static constexpr std::span valueDelimiter{VALUE_DELIM, sizeof(VALUE_DELIM) - 1};
AdcKeyValueMessage1(ByteSeqT& byte_seq) : _byteSequence(byte_seq) {}
virtual ~AdcKeyValueMessage1() = default;
template <typename T>
requires(traits::adc_char_view<T> && std::ranges::contiguous_range<ByteSeqT>) ||
traits::adc_output_char_range<T>
auto key() const
{
if constexpr (traits::adc_char_view<T> && std::ranges::contiguous_range<ByteSeqT>) {
auto bs = utils::AdcTrimSpacesView<T>(_byteSequence, utils::AdcTrimType::TRIM_LEFT);
auto found = std::ranges::search(bs, keyValueDelimiter);
// if (found.empty) { // no value
// return bs;
// }
return utils::AdcTrimSpacesView<T>(std::span<const char>(bs.begin(), found.begin()),
utils::AdcTrimType::TRIM_RIGHT);
} else {
T res;
auto bs = _byteSequence | std::views::drop_while([](const auto& ch) { return ch = ' '; });
auto found = std::ranges::search(bs, keyValueDelimiter);
std::ranges::copy(bs.begin(), found.begin(), std::back_inserter(res));
// if (found.empty()) { // no value
// std::ranges::copy(bs, std::back_inserter(res));
// } else {
// std::ranges::copy(bs.begin(), found.begin(), std::back_inserter(res));
// }
return res;
}
}
auto key() const
{
if constexpr (std::ranges::contiguous_range<ByteSeqT>) {
return key<std::string_view>();
} else {
return key<std::string>();
}
}
template <typename T>
requires(traits::adc_char_view<T> && std::ranges::contiguous_range<ByteSeqT>) ||
traits::adc_output_char_range<T>
auto value() const
{
if constexpr (traits::adc_char_view<T> && std::ranges::contiguous_range<ByteSeqT>) {
auto bs = utils::AdcTrimSpacesView<T>(_byteSequence, utils::AdcTrimType::TRIM_LEFT);
auto found = std::ranges::search(bs, keyValueDelimiter);
// if (found.empty()) { // no value
// return T();
// }
return T(found.end(), _byteSequence.end());
} else {
T res;
auto bs = _byteSequence | std::views::drop_while([](const auto& ch) { return ch = ' '; });
auto found = std::ranges::search(bs, keyValueDelimiter);
if (!found.empty()) {
std::ranges::copy(found.end(), _byteSequence.end(), std::back_inserter(res));
}
return res;
}
}
auto value() const
{
if constexpr (std::ranges::contiguous_range<ByteSeqT>) {
return value<std::string_view>();
} else {
return value<std::string>();
}
}
template <typename KeyT, typename ValueT>
requires traits::adc_output_char_range<ByteSeqT>
AdcKeyValueMessage1& setKeyValue(KeyT&& key, ValueT&& value)
{
if (std::ranges::size(_byteSequence)) {
_byteSequence = _byteSequence();
}
std::ranges::copy(
utils::AdcDefaultValueConverter<KEY_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<KEY_VALUE_DELIM>::template serialize(std::forward<ValueT>(value)),
std::back_inserter(_byteSequence));
return *this;
}
template <typename ValueT>
AdcKeyValueMessage1& setValue(ValueT&& value)
{
std::vector<char> kw;
std::ranges::copy(key<std::span<const char>>(), std::back_inserter(kw));
return setKeyValue(kw, std::forward<ValueT>(value));
}
protected:
ByteSeqT& _byteSequence;
};
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>
{
using base_t = AdcKeyValueMessage1<ByteSeqT, KEY_PARAM_DELIM, COMPOSITE_PARAM_DELIM>;
public:
static constexpr std::span keyParamDelimiter{KEY_PARAM_DELIM, sizeof(KEY_PARAM_DELIM) - 1};
static constexpr std::span paramParamDelimiter{PARAM_PARAM_DELIM, sizeof(PARAM_PARAM_DELIM) - 1};
static constexpr std::span compParamDelimiter{COMPOSITE_PARAM_DELIM, sizeof(COMPOSITE_PARAM_DELIM) - 1};
AdcDeviceNetMessage(ByteSeqT& byte_seq) : base_t(byte_seq) {}
template <traits::adc_char_view VT>
VT keyword() const
{
// auto v = utils::AdcTrimSpaces(base_t::template key<VT>());
// return VT(std::begin(v), std::end(v));
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);
auto found = std::ranges::search(bs, keyParamDelimiter);
if (found.empty()) { // only keyword
return VT(bs.begin(), bs.end());
}
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())
{
auto val = base_t::template value<std::ranges::range_value_t<R>>();
// auto p = utils::AdcTokenManip(val).tokens(start, N);
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;
}
auto params(size_t start = 0, size_t N = std::numeric_limits<size_t>::max())
{
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);
return res;
}
};
} // namespace adc