...
This commit is contained in:
parent
eb64c6e56d
commit
0d07fb77a6
@ -53,7 +53,7 @@ protected:
|
|||||||
ByteStorageT _byteStorage;
|
ByteStorageT _byteStorage;
|
||||||
StorageSeqT _storageSequence;
|
StorageSeqT _storageSequence;
|
||||||
|
|
||||||
AdcNetMessageInterface() = default;
|
AdcNetMessageInterface() : _byteStorage(), _storageSequence({_byteStorage}) {};
|
||||||
|
|
||||||
template <traits::adc_input_char_range T, traits::adc_input_char_range... Ts>
|
template <traits::adc_input_char_range T, traits::adc_input_char_range... Ts>
|
||||||
AdcNetMessageInterface(const T& v, const Ts&... vs) : AdcNetMessageInterface()
|
AdcNetMessageInterface(const T& v, const Ts&... vs) : AdcNetMessageInterface()
|
||||||
@ -69,12 +69,22 @@ protected:
|
|||||||
AdcNetMessageInterface& operator=(const AdcNetMessageInterface&) = default;
|
AdcNetMessageInterface& operator=(const AdcNetMessageInterface&) = default;
|
||||||
AdcNetMessageInterface& operator=(AdcNetMessageInterface&&) = default;
|
AdcNetMessageInterface& operator=(AdcNetMessageInterface&&) = default;
|
||||||
|
|
||||||
|
|
||||||
virtual void updateState() = 0;
|
virtual void updateState() = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef ByteStorageT byte_storage_t;
|
typedef ByteStorageT byte_storage_t;
|
||||||
typedef StorageSeqT storage_seq_t;
|
typedef StorageSeqT storage_seq_t;
|
||||||
|
|
||||||
|
bool messageEmpty() const { return byteSize() == 0; }
|
||||||
|
|
||||||
|
bool byteStorageEmpty() const
|
||||||
|
{
|
||||||
|
size_t sz = std::ranges::distance(_byteStorage.begin(), _byteStorage.end());
|
||||||
|
return sz == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template <traits::adc_input_char_range T, traits::adc_input_char_range... Ts>
|
template <traits::adc_input_char_range T, traits::adc_input_char_range... Ts>
|
||||||
void appendBytes(const T& v, const Ts&... vs)
|
void appendBytes(const T& v, const Ts&... vs)
|
||||||
{
|
{
|
||||||
@ -88,6 +98,26 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <traits::formattable T, traits::formattable... Ts>
|
||||||
|
void appendBytes(const T& v, const Ts&... vs)
|
||||||
|
{
|
||||||
|
std::format_to(std::back_inserter(_byteStorage), v);
|
||||||
|
|
||||||
|
if constexpr (sizeof...(Ts)) {
|
||||||
|
appendBytes(vs...);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::input_iterator IterT>
|
||||||
|
void appendBytes(IterT begin, IterT end)
|
||||||
|
{
|
||||||
|
std::copy(begin, end, std::back_inserter(_byteStorage));
|
||||||
|
|
||||||
|
updateState();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template <traits::adc_input_char_range T, traits::adc_input_char_range... Ts>
|
template <traits::adc_input_char_range T, traits::adc_input_char_range... Ts>
|
||||||
void setBytes(const T& v, const Ts&... vs)
|
void setBytes(const T& v, const Ts&... vs)
|
||||||
{
|
{
|
||||||
@ -98,18 +128,22 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <traits::formattable T, traits::formattable... Ts>
|
||||||
|
void setBytes(const T& v, const Ts&... vs)
|
||||||
|
{
|
||||||
|
_byteStorage = ByteStorageT();
|
||||||
|
appendBytes(v, vs...);
|
||||||
|
|
||||||
|
updateState();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template <std::input_iterator IterT>
|
template <std::input_iterator IterT>
|
||||||
void setBytes(IterT begin, IterT end)
|
void setBytes(IterT begin, IterT end)
|
||||||
{
|
{
|
||||||
_byteStorage = ByteStorageT(begin, end);
|
_byteStorage = ByteStorageT(begin, end);
|
||||||
|
|
||||||
updateState();
|
appendBytes(begin, end);
|
||||||
}
|
|
||||||
|
|
||||||
template <std::input_iterator IterT>
|
|
||||||
void appendBytes(IterT begin, IterT end)
|
|
||||||
{
|
|
||||||
std::copy(begin, end, std::back_inserter(_byteStorage));
|
|
||||||
|
|
||||||
updateState();
|
updateState();
|
||||||
}
|
}
|
||||||
@ -139,9 +173,9 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* GENERIC (NOTHING SPECIAL) NETWORK MESSAGE */
|
||||||
|
|
||||||
template <std::ranges::output_range<char> ByteStorageT = std::vector<char>,
|
template <std::ranges::output_range<char> ByteStorageT = std::vector<char>>
|
||||||
typename MessageViewT = traits::AdcTheSameTypeTag>
|
|
||||||
class AdcGenericNetMessage
|
class AdcGenericNetMessage
|
||||||
: public AdcNetMessageInterface<ByteStorageT, std::array<std::reference_wrapper<const ByteStorageT>, 1>>
|
: public AdcNetMessageInterface<ByteStorageT, std::array<std::reference_wrapper<const ByteStorageT>, 1>>
|
||||||
{
|
{
|
||||||
@ -151,50 +185,13 @@ public:
|
|||||||
using typename base_t::byte_storage_t;
|
using typename base_t::byte_storage_t;
|
||||||
using typename base_t::storage_seq_t;
|
using typename base_t::storage_seq_t;
|
||||||
|
|
||||||
using base_t::appendBytes;
|
// using base_t::appendBytes;
|
||||||
using base_t::setBytes;
|
// using base_t::setBytes;
|
||||||
|
|
||||||
using message_view_t =
|
|
||||||
std::conditional_t<std::is_same_v<MessageViewT, traits::AdcTheSameTypeTag>, ByteStorageT, MessageViewT>;
|
|
||||||
|
|
||||||
AdcGenericNetMessage() = default;
|
|
||||||
|
|
||||||
template <std::convertible_to<MessageViewT> T,
|
|
||||||
traits::adc_to_bytes_func_c<ByteStorageT, MessageViewT> CONVT =
|
|
||||||
decltype(utils::AdcDefaultValueConverter<>::serialize<ByteStorageT, T>)>
|
|
||||||
AdcGenericNetMessage(T&& v, CONVT&& conv_func = utils::AdcDefaultValueConverter<>::serialize<ByteStorageT, T>)
|
|
||||||
: AdcGenericNetMessage()
|
|
||||||
{
|
|
||||||
setMessage(std::forward<T>(v), std::forward<CONVT>(conv_func));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
using base_t::base_t;
|
||||||
|
|
||||||
virtual ~AdcGenericNetMessage() = default;
|
virtual ~AdcGenericNetMessage() = default;
|
||||||
|
|
||||||
template <std::convertible_to<MessageViewT> T,
|
|
||||||
traits::adc_to_bytes_func_c<ByteStorageT, message_view_t> CONVT =
|
|
||||||
decltype(utils::AdcDefaultValueConverter<>::serialize<ByteStorageT, T>)>
|
|
||||||
void setMessage(T&& v, CONVT&& conv_func = utils::AdcDefaultValueConverter<>::serialize<ByteStorageT, T>)
|
|
||||||
{
|
|
||||||
if constexpr (std::is_same_v<MessageViewT, traits::AdcTheSameTypeTag>) {
|
|
||||||
this->setBytes(std::forward<T>(v));
|
|
||||||
} else {
|
|
||||||
_messageView(std::forward<T>(v));
|
|
||||||
this->_byteStorage = std::forward<CONVT>(conv_func)(_messageView);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
message_view_t messageView() const
|
|
||||||
{
|
|
||||||
if constexpr (std::is_same_v<MessageViewT, traits::AdcTheSameTypeTag>) {
|
|
||||||
return this->_byteStorage;
|
|
||||||
} else {
|
|
||||||
return _messageView;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const storage_seq_t& storageSeq() override
|
const storage_seq_t& storageSeq() override
|
||||||
{
|
{
|
||||||
this->_storageSequence[0] = this->_byteStorage;
|
this->_storageSequence[0] = this->_byteStorage;
|
||||||
@ -202,54 +199,203 @@ public:
|
|||||||
return this->_storageSequence;
|
return this->_storageSequence;
|
||||||
};
|
};
|
||||||
|
|
||||||
// factory function
|
protected:
|
||||||
|
void updateState() override {}
|
||||||
|
};
|
||||||
|
|
||||||
template <traits::adc_input_char_range BT,
|
|
||||||
traits::adc_from_bytes_func_c<ByteStorageT, message_view_t> CONVT =
|
namespace constants
|
||||||
decltype(utils::AdcDefaultValueConverter<>::deserialize<message_view_t, ByteStorageT>)>
|
|
||||||
static AdcGenericNetMessage fromBytes(
|
|
||||||
BT&& bytes,
|
|
||||||
CONVT&& conv_func = utils::AdcDefaultValueConverter<>::deserialize<message_view_t, ByteStorageT>)
|
|
||||||
{
|
{
|
||||||
AdcGenericNetMessage msg;
|
|
||||||
msg.setBytes(std::forward<BT>(bytes));
|
|
||||||
|
|
||||||
if constexpr (!std::is_same_v<MessageViewT, traits::AdcTheSameTypeTag>) {
|
static constexpr char ADC_DEFAULT_TOKEN_DELIMITER[] = " ";
|
||||||
msg._messageView = conv_func(msg._byteStorage);
|
static constexpr char ADC_DEFAULT_KEY_PARAM_DELIMITER[] = " ";
|
||||||
}
|
static constexpr char ADC_DEFAULT_PARAM_PARAM_DELIMITER[] = " ";
|
||||||
|
|
||||||
return msg;
|
} // namespace constants
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <std::input_iterator IterT,
|
template <const char* TOKEN_DELIM = constants::ADC_DEFAULT_TOKEN_DELIMITER,
|
||||||
traits::adc_from_bytes_func_c<ByteStorageT, message_view_t> CONVT =
|
std::ranges::output_range<char> ByteStorageT = std::vector<char>>
|
||||||
decltype(utils::AdcDefaultValueConverter<>::deserialize<message_view_t, ByteStorageT>)>
|
class AdcTokenNetMessage : public AdcGenericNetMessage<ByteStorageT>
|
||||||
static AdcGenericNetMessage fromBytes(
|
|
||||||
IterT begin,
|
|
||||||
IterT end,
|
|
||||||
CONVT&& conv_func = utils::AdcDefaultValueConverter<>::deserialize<message_view_t, ByteStorageT>)
|
|
||||||
{
|
{
|
||||||
AdcGenericNetMessage msg;
|
using base_t = AdcGenericNetMessage<ByteStorageT>;
|
||||||
msg.setBytes(begin, end);
|
|
||||||
|
|
||||||
if constexpr (!std::is_same_v<MessageViewT, traits::AdcTheSameTypeTag>) {
|
public:
|
||||||
msg._messageView = conv_func(msg._byteStorage);
|
static constexpr std::string_view tokenDelimiter{TOKEN_DELIM};
|
||||||
|
|
||||||
|
using typename base_t::byte_storage_t;
|
||||||
|
using typename base_t::storage_seq_t;
|
||||||
|
|
||||||
|
using base_t::base_t;
|
||||||
|
|
||||||
|
virtual ~AdcTokenNetMessage() = default;
|
||||||
|
|
||||||
|
template <std::ranges::input_range R>
|
||||||
|
void appendTokens(const R& r)
|
||||||
|
{
|
||||||
|
using el_t = std::ranges::range_value_t<R>;
|
||||||
|
static_assert(traits::adc_input_char_range<el_t> || traits::formattable<el_t>,
|
||||||
|
"INVALID TYPE OF INPUT TOKENS!!!");
|
||||||
|
|
||||||
|
size_t n_toks = 0;
|
||||||
|
if ((n_toks = std::ranges::distance(r.begin(), r.end())) == 0) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return msg;
|
if (!this->byteStorageEmpty()) {
|
||||||
|
this->appendBytes(tokenDelimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto v_start = r | std::views::take(n_toks - 1);
|
||||||
|
for (const auto& el : v_start) {
|
||||||
|
this->appendBytes(el);
|
||||||
|
this->appendBytes(tokenDelimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->appendBytes(*(r.end()--)); // last element
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <std::ranges::input_range R>
|
||||||
|
void setTokens(const R& r)
|
||||||
|
{
|
||||||
|
this->_byteStorage = ByteStorageT();
|
||||||
|
appendTokens(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::ranges::output_range<ByteStorageT> R>
|
||||||
|
void tokens(R& r)
|
||||||
|
{
|
||||||
|
if (this->byteStorageEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ranges::copy(this->_byteStorage | std::views::split(AdcTokenNetMessage::tokenDelimiter),
|
||||||
|
std::back_inserter(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MessageViewT _messageView;
|
// std::vector<ByteStorageT> _tokens;
|
||||||
|
|
||||||
void updateState() override
|
void updateState() override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <const char* KEY_PARAM_DELIM = constants::ADC_DEFAULT_KEY_PARAM_DELIMITER,
|
||||||
|
const char* PARAM_PARAM_DELIM = constants::ADC_DEFAULT_PARAM_PARAM_DELIMITER,
|
||||||
|
std::ranges::output_range<char> ByteStorageT = std::vector<char>>
|
||||||
|
class AdcKeyParamNetMessage : public AdcGenericNetMessage<ByteStorageT>
|
||||||
{
|
{
|
||||||
if constexpr (!std::is_same_v<MessageViewT, traits::AdcTheSameTypeTag>) {
|
using base_t = AdcGenericNetMessage<ByteStorageT>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static constexpr std::string_view keyparamDelimiter{KEY_PARAM_DELIM};
|
||||||
|
static constexpr std::string_view paramparamDelimiter{PARAM_PARAM_DELIM};
|
||||||
|
|
||||||
|
using typename base_t::byte_storage_t;
|
||||||
|
using typename base_t::storage_seq_t;
|
||||||
|
|
||||||
|
using base_t::base_t;
|
||||||
|
|
||||||
|
virtual ~AdcKeyParamNetMessage() = default;
|
||||||
|
|
||||||
|
// key and params
|
||||||
|
template <typename KeyT, typename... ParamTs>
|
||||||
|
void setKeyParam(KeyT&& key, ParamTs&&... params)
|
||||||
|
{
|
||||||
|
this->_byteStorage = ByteStorageT();
|
||||||
|
|
||||||
|
if constexpr (sizeof...(ParamTs)) {
|
||||||
|
this->setBytes(std::forward<KeyT>(key), keyparamDelimiter);
|
||||||
|
setKeyParamHelper(std::forward<ParamTs>(params)...);
|
||||||
|
} else {
|
||||||
|
this->setBytes(std::forward<KeyT>(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <traits::adc_output_char_range R>
|
||||||
|
R key() const
|
||||||
|
{
|
||||||
|
R val;
|
||||||
|
|
||||||
|
if (this->byteStorageEmpty()) {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto v = this->_byteStorage | std::views::split(keyparamDelimiter);
|
||||||
|
|
||||||
|
std::ranges::copy(v | std::views::take(1), std::back_inserter(val));
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::ranges::output_range<ByteStorageT> R>
|
||||||
|
R params(size_t start = 0, size_t N = std::numeric_limits<size_t>::max()) const
|
||||||
|
{
|
||||||
|
R pars;
|
||||||
|
|
||||||
|
if (this->byteStorageEmpty() || !N) {
|
||||||
|
return pars;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto v = this->_byteStorage | std::views::split(keyparamDelimiter);
|
||||||
|
|
||||||
|
size_t k, num = N, n_pars = std::ranges::distance(v.begin(), v.end()) - 1;
|
||||||
|
if (!n_pars) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
n_pars = 0;
|
||||||
|
for (auto& p : v | std::views::drop(1)) {
|
||||||
|
auto pv = p | std::views::split(paramparamDelimiter);
|
||||||
|
n_pars += std::ranges::distance(pv.begin(), pv.end());
|
||||||
|
if (n_pars < start) {
|
||||||
|
k = start - n_pars;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
k = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ranges::copy(pv | std::views::drop(k) | std::views::take(num), std::back_inserter(pars));
|
||||||
|
num -= std::ranges::distance(pars.begin(), pars.end());
|
||||||
|
if (!num) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pars;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <traits::adc_output_char_range R>
|
||||||
|
R paramsBytes(size_t start = 0, size_t N = std::numeric_limits<size_t>::max()) const
|
||||||
|
{
|
||||||
|
R pars_bytes;
|
||||||
|
|
||||||
|
if (this->byteStorageEmpty() || !N) {
|
||||||
|
return pars_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto p = params<std::vector<ByteStorageT>>(start, N);
|
||||||
|
|
||||||
|
if (std::ranges::distance(p.begin(), p.end())) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return pars_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
template <typename ParamT, typename... ParamTs>
|
||||||
|
void setKeyParamHelper(ParamT&& param, ParamTs&&... params)
|
||||||
|
{
|
||||||
|
this->appendBytes(std::forward<ParamT>(param));
|
||||||
|
|
||||||
|
if constexpr (sizeof...(ParamTs)) {
|
||||||
|
this->appendBytes(paramparamDelimiter);
|
||||||
|
setKeyParamHelper(std::forward<ParamTs>(params)...);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace adc
|
} // namespace adc
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user