This commit is contained in:
Timur A. Fatkhullin 2024-06-03 23:57:03 +03:00
parent c0316937e3
commit 7dabd9394d

View File

@ -14,7 +14,7 @@ namespace adc
{
template <traits::adc_output_char_range ByteStorageT = std::string, traits::adc_char_view ByteViewT = std::string_view>
class AdcGenericNetMessage
class AdcNetMessageCommonInterface
{
virtual bool empty() const { return std::ranges::distance(_bytes.begin(), _bytes.end()) == 0; }
@ -33,9 +33,7 @@ class AdcGenericNetMessage
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>
template <traits::adc_range_of_view_char_range R>
R bytesView() const
{
R r;
@ -45,17 +43,95 @@ class AdcGenericNetMessage
return r;
}
virtual std::vector<ByteViewT> bytesView() const { return bytesView<std::vector<ByteViewT>>(); }
virtual std::vector<ByteViewT> bytesView() const { return bytesView<std::vector<ByteViewT>>(); }
protected:
ByteStorageT _bytes;
AdcNetMessageCommonInterface() = default;
virtual ~AdcNetMessageCommonInterface() = default;
AdcNetMessageCommonInterface(const AdcNetMessageCommonInterface&) = default;
AdcNetMessageCommonInterface(AdcNetMessageCommonInterface&&) = default;
AdcNetMessageCommonInterface& operator=(const AdcNetMessageCommonInterface&) = default;
AdcNetMessageCommonInterface& operator=(AdcNetMessageCommonInterface&&) = default;
template <typename T, typename... Ts>
void convertToBytes(ByteViewT& res, const T& v, const Ts&... vs)
{
if constexpr (std::is_array_v<std::remove_cvref_t<T>>) { // to handle with trailing '\0' in plain char array
convertToBytes(std::string_view(v), vs...);
} else {
if constexpr (traits::adc_input_char_range<T>) {
std::ranges::copy(v, std::back_inserter(res));
} else if constexpr (std::convertible_to<T, ByteStorageT>) {
convertToBytes(static_cast<ByteViewT>(v), vs...);
} else if constexpr (traits::formattable<T>) {
std::format_to(std::back_inserter(res), "{}", v);
} else {
static_assert(false, "UNSUPPORTED TYPE!!!");
}
}
if constexpr (sizeof...(Ts)) {
convertToBytes(vs...);
}
}
};
// Generic message class
template <traits::adc_output_char_range ByteStorageT = std::string, traits::adc_char_view ByteViewT = std::string_view>
class AdcGenericNetMessage : public AdcNetMessageCommonInterface<ByteStorageT, ByteViewT>
{
using base_t = AdcNetMessageCommonInterface<ByteStorageT, ByteViewT>;
public:
using base_t::base_t;
using base_t::bytes;
using base_t::byteView;
template <typename T, typename... Ts>
void appendBytes(const T& v, const Ts&... vs)
{
this->convertToBytes(this->_bytes, v, vs...);
}
template <typename T, typename... Ts>
void setBytes(const T& v, const Ts&... vs)
{
this->_bytes = ByteStorageT();
appendBytes(v, vs...);
}
template <std::input_iterator IT>
void appendFromBytes(IT begin, IT end)
requires std::same_as<std::iter_value_t<IT>, char>
{
std::copy(begin, end, std::back_inserter(this->_bytes));
}
template <std::input_iterator IT>
void setFromBytes(IT begin, IT end)
requires std::same_as<std::iter_value_t<IT>, char>
{
this->_bytes = ByteStorageT();
appendFromBytes(begin, end);
}
};
namespace constants
{
static constexpr char ADC_DEFAULT_TOKEN_DELIMITER[] = " ";
static constexpr char ADC_DEFAULT_KEY_TOKEN_DELIMITER[] = " ";
@ -65,15 +141,30 @@ static constexpr char ADC_DEFAULT_KEY_TOKEN_DELIMITER[] = " ";
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>
class AdcTokenNetMessage : public AdcNetMessageCommonInterface<ByteStorageT, ByteViewT>
{
using base_t = AdcGenericNetMessage<ByteStorageT, ByteViewT>;
using base_t = AdcNetMessageCommonInterface<ByteStorageT, ByteViewT>;
public:
static constexpr std::string_view tokenDelimiter{TOKEN_DELIM};
virtual bool empty() const { return _tokens.empty(); }
AdcTokenNetMessage() = default;
template <typename T, typename... Ts>
AdcTokenNetMessage(const T& v, const Ts&... vs) : AdcTokenNetMessage()
{
setTokens(v, vs...);
}
virtual ~AdcTokenNetMessage() = default;
virtual bool empty() const
{
//
return _tokens.empty();
}
template <traits::adc_output_char_range R>
R bytes() const
@ -85,22 +176,13 @@ public:
}
// 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>
template <traits::adc_range_of_view_char_range R>
R bytesView() const
{
R r;
@ -109,21 +191,13 @@ public:
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>
template <std::ranges::output_range<ByteStorageT> R>
R tokens() const
{
R r;
@ -143,6 +217,65 @@ public:
return tokens<std::vector<ByteStorageT>>();
}
template <typename T, typename... Ts>
void appendTokens(const T& v, const Ts&... vs)
{
if constexpr (traits::adc_input_char_range<T> || traits::formattable<T>) {
this->convertToBytes(_tokens.emplace_back(), v);
} else if constexpr (std::ranges::input_range<T>) {
using el_t = std::ranges::range_value_t<T>;
static_assert(traits::adc_input_char_range<el_t> || traits::formattable<el_t>,
"INVALID TYPE OF INPUT TOKENS!!!");
if (std::ranges::distance(v.begin(), v.end())) {
for (const auto& el : v) {
this->convertToBytes(_tokens.emplace_back(), el);
}
}
} else {
static_assert(false, "UNSUPPORTED (CANNOT BE SERIALIZED TO BYTES) TYPE OF INPUT TOKENS!!!");
}
if constexpr (sizeof...(Ts)) {
appendTokens(vs...);
}
}
template <typename T, typename... Ts>
void setTokens(const T& v, const Ts&... vs)
{
_tokens.clear();
appendTokens(v, vs...);
}
template <std::input_iterator IT>
void appendFromBytes(IT begin, IT end)
requires std::same_as<std::iter_value_t<IT>, char>
{
auto it = begin, start_it = begin;
do {
it = std::search(start_it, end, tokenDelimiter.begin(), tokenDelimiter.end());
std::copy(start_it, it, std::back_inserter(_tokens.emplace_back()));
start_it = it + tokenDelimiter.size();
} while (it != end);
}
template <std::input_iterator IT>
void setFromBytes(IT begin, IT end)
requires std::same_as<std::iter_value_t<IT>, char>
{
_tokens.clear();
appendFromBytes(begin, end);
}
protected:
std::vector<ByteStorageT> _tokens;
};
@ -152,10 +285,10 @@ protected:
// 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>
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>;
@ -163,8 +296,11 @@ class AdcKeyTokenNetMessage : public AdcTokenNetMessage<TOKEN_DELIM, ByteStorage
public:
static constexpr std::string_view keytokenDelim{KEY_TOKEN_DELIM};
using base_t::appendTokens;
using base_t::setTokens;
using base_t::tokens;
virtual bool empty() const
{
auto N = std::distance(this->_bytes.begin(), this->_bytes.end());
@ -172,7 +308,7 @@ public:
return (N == 0) && this->_tokens.empty();
}
template<traits::adc_output_char_range R>
template <traits::adc_output_char_range R>
R keyBytes() const
{
R r;
@ -190,7 +326,7 @@ public:
}
template<traits::adc_char_view R>
template <traits::adc_char_view R>
R keyView() const
{
//
@ -198,13 +334,14 @@ public:
}
ByteViewT keyView() const {
ByteViewT keyView() const
{
//
return ByteViewT{this->_bytes.begin(), this->_bytes.end()};
}
template<traits::adc_output_char_range R>
template <traits::adc_output_char_range R>
R bytes() const
{
R r;
@ -213,17 +350,17 @@ public:
return r;
}
std::ranges::copy(this->_bytes, std::back_inserter(r)); // keyword
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
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>
template <traits::adc_range_of_view_char_range R>
R bytesView() const
{
R r;
@ -232,10 +369,10 @@ public:
return r;
}
std::back_inserter(r) = {this->_bytes.begin(), this->_bytes.end()}; // keyword
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
std::back_inserter(r) = {keytokenDelim.begin(), keytokenDelim.end()}; // keyword-to-tokens delimiter
utils::AdcReturnRangeElementsView(this->_tokens, base_t::tokenDelimiter, r);
}