251 lines
6.0 KiB
C++
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
|