ADC/net/adc_netmsg.h
2024-06-03 18:02:46 +03:00

251 lines
6.0 KiB
C++

#pragma once
#include <algorithm>
#include <string>
#include <vector>
#include "../common/adc_traits.h"
#include "../common/adc_utils.h"
namespace adc
{
template <traits::adc_output_char_range ByteStorageT = std::string, traits::adc_char_view ByteViewT = std::string_view>
class AdcGenericNetMessage
{
virtual bool empty() const { return std::ranges::distance(_bytes.begin(), _bytes.end()) == 0; }
// get a copy of message bytes
template <traits::adc_output_char_range R>
R bytes() const
{
R r;
std::ranges::copy(_bytes, std::back_inserter(r));
return r;
}
virtual ByteStorageT bytes() const { return bytes<ByteStorageT>(); }
// get a view of message bytes
// template <std::ranges::range R>
// requires std::ranges::view<std::ranges::range_value_t<R>>
template<traits::adc_range_of_view_char_range R>
R bytesView() const
{
R r;
r.emplace_back(_bytes.begin(), _bytes.end());
return r;
}
virtual std::vector<ByteViewT> bytesView() const { return bytesView<std::vector<ByteViewT>>(); }
protected:
ByteStorageT _bytes;
};
namespace constants
{
static constexpr char ADC_DEFAULT_TOKEN_DELIMITER[] = " ";
static constexpr char ADC_DEFAULT_KEY_TOKEN_DELIMITER[] = " ";
} // namespace constants
template <const char* TOKEN_DELIM = constants::ADC_DEFAULT_TOKEN_DELIMITER,
traits::adc_output_char_range ByteStorageT = std::string,
traits::adc_char_view ByteViewT = std::string_view>
class AdcTokenNetMessage : public AdcGenericNetMessage<ByteStorageT, ByteViewT>
{
using base_t = AdcGenericNetMessage<ByteStorageT, ByteViewT>;
public:
static constexpr std::string_view tokenDelimiter{TOKEN_DELIM};
virtual bool empty() const { return _tokens.empty(); }
template <traits::adc_output_char_range R>
R bytes() const
{
R r;
if (_tokens.empty()) {
return r;
}
// std::ranges::for_each(_tokens | std::views::take(_tokens.size()-1), [&r](const auto& el) {
// std::ranges::copy(el, std::back_inserter(r));
// std::ranges::copy(tokenDelimiter, std::back_inserter(r));
// });
// std::ranges::copy(_tokens.back(), std::back_inserter(r));
utils::AdcJoinRange(_tokens, tokenDelimiter, r);
return r;
}
// template <std::ranges::range R>
// requires std::ranges::view<std::ranges::range_value_t<R>>
template<traits::adc_range_of_view_char_range R>
R bytesView() const
{
R r;
if (_tokens.empty()) {
return r;
}
// std::ranges::for_each(_tokens | std::views::take(_tokens.size()-1), [&r](const auto& el) {
// // std::ranges::range_value_t<R> v{el.begin(), el.end()};
// std::back_inserter(r) = {el.begin(), el.end()};
// std::back_inserter(r) = {tokenDelimiter.begin(), tokenDelimiter.end()};
// });
// std::back_inserter(r) = {_tokens.back().begin(), _tokens.back().end()};
utils::AdcReturnRangeElementsView(_tokens, tokenDelimiter, r);
return r;
}
template<std::ranges::output_range<ByteStorageT> R>
R tokens() const
{
R r;
if (_tokens.empty()) {
return r;
}
std::ranges::copy(_tokens, std::back_inserter(r));
return r;
}
std::vector<ByteStorageT> tokens() const
{
//
return tokens<std::vector<ByteStorageT>>();
}
protected:
std::vector<ByteStorageT> _tokens;
};
// special type of tokenized message:
// the first token is keyword
// the other - just tokens
// delimiter between keyword and other tokens may differ from token-to-token one
template<const char *KEY_TOKEN_DELIM = constants::ADC_DEFAULT_KEY_TOKEN_DELIMITER,
const char *TOKEN_DELIM = constants::ADC_DEFAULT_TOKEN_DELIMITER,
traits::adc_output_char_range ByteStorageT = std::string,
traits::adc_char_view ByteViewT = std::string_view>
class AdcKeyTokenNetMessage : public AdcTokenNetMessage<TOKEN_DELIM, ByteStorageT, ByteViewT>
{
using base_t = AdcTokenNetMessage<TOKEN_DELIM, ByteStorageT, ByteViewT>;
public:
static constexpr std::string_view keytokenDelim{KEY_TOKEN_DELIM};
using base_t::tokens;
virtual bool empty() const
{
auto N = std::distance(this->_bytes.begin(), this->_bytes.end());
return (N == 0) && this->_tokens.empty();
}
template<traits::adc_output_char_range R>
R keyBytes() const
{
R r;
std::ranges::copy(this->_bytes, r);
return r;
}
ByteStorageT keyBytes() const
{
//
return this->_bytes;
}
template<traits::adc_char_view R>
R keyView() const
{
//
return R{this->_bytes.begin(), this->_bytes.end()};
}
ByteViewT keyView() const {
//
return ByteViewT{this->_bytes.begin(), this->_bytes.end()};
}
template<traits::adc_output_char_range R>
R bytes() const
{
R r;
if (this->_bytes.empty() && this->_tokens.empty()) {
return r;
}
std::ranges::copy(this->_bytes, std::back_inserter(r)); // keyword
if (!this->_tokens.empty()) {
std::ranges::copy(keytokenDelim, std::back_inserter(r)); // keyword-to-tokens delimiter
utils::AdcJoinRange(this->_tokens, base_t::tokenDelimiter, r);
}
return r;
}
template<traits::adc_range_of_view_char_range R>
R bytesView() const
{
R r;
if (this->_bytes.empty() && this->_tokens.empty()) {
return r;
}
std::back_inserter(r) = {this->_bytes.begin(), this->_bytes.end()}; // keyword
if (!this->_tokens.empty()) {
std::back_inserter(r) = {keytokenDelim.begin(), keytokenDelim.end()}; // keyword-to-tokens delimiter
utils::AdcReturnRangeElementsView(this->_tokens, base_t::tokenDelimiter, r);
}
return r;
}
protected:
// _bytes: keyword
// _tokens: tokens
};
} // namespace adc