diff --git a/common/adc_traits.h b/common/adc_traits.h index f37dc82..a2c67fd 100644 --- a/common/adc_traits.h +++ b/common/adc_traits.h @@ -42,6 +42,10 @@ concept adc_input_char_range = std::ranges::input_range && std::is_same_v>, CharT>; +template +concept adc_char_view = std::ranges::view && std::same_as, char>; + + // deduce returned type of callable // template // using adc_retval_t = std::invoke_result_t>; diff --git a/net/adc_netmsg.h b/net/adc_netmsg.h new file mode 100644 index 0000000..df87744 --- /dev/null +++ b/net/adc_netmsg.h @@ -0,0 +1,109 @@ +#pragma once + + + +#include +#include +#include + + +#include "../common/adc_traits.h" + +namespace adc +{ + +template +class AdcGenericNetMessage +{ + // get a copy of message bytes + template + R bytes() const + { + R r; + std::ranges::copy(_bytes, std::back_inserter(r)); + + return r; + } + + + virtual ByteStorageT bytes() const { return bytes(); } + + // get a view of message bytes + template + R bytesView() const + { + return R{_bytes.begin(), _bytes.end()}; + } + + virtual ByteViewT bytesView() const { return bytesView(); } + +protected: + ByteStorageT _bytes; +}; + + + +namespace constants +{ + +static constexpr char ADC_DEFAULT_TOKEN_DELIMITER[] = " "; +static constexpr char ADC_DEFAULT_KEY_PARAM_DELIMITER[] = " "; +static constexpr char ADC_DEFAULT_PARAM_PARAM_DELIMITER[] = " "; + +} // namespace constants + + +template +class AdcTokenNetMessage : public AdcGenericNetMessage +{ + using base_t = AdcGenericNetMessage; + +public: + static constexpr std::string_view tokenDelimiter{TOKEN_DELIM}; + + template + R bytes() const + { + R r; + + if (_tokens.empty()) { + return r; + } + + + std::ranges::for_each(_tokens | std::views::take(_tokens.size()), [&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)); + + return r; + } + + + template + requires std::ranges::view> + R bytesView() const + { + R r; + + std::ranges::for_each(_tokens | std::views::take(_tokens.size()), [&r](const auto& el) { + std::ranges::range_value_t 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()}; + + return r; + } + +protected: + std::vector _tokens; +}; + + +} // namespace adc