#pragma once #include #include #include #include "../common/adc_traits.h" #include "../common/adc_utils.h" namespace adc { template class AdcGenericNetMessage { virtual bool empty() const { return std::ranges::distance(_bytes.begin(), _bytes.end()) == 0; } // 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 // requires std::ranges::view> template R bytesView() const { R r; r.emplace_back(_bytes.begin(), _bytes.end()); return r; } virtual std::vector bytesView() const { return bytesView>(); } protected: ByteStorageT _bytes; }; namespace constants { static constexpr char ADC_DEFAULT_TOKEN_DELIMITER[] = " "; static constexpr char ADC_DEFAULT_KEY_TOKEN_DELIMITER[] = " "; } // namespace constants template class AdcTokenNetMessage : public AdcGenericNetMessage { using base_t = AdcGenericNetMessage; public: static constexpr std::string_view tokenDelimiter{TOKEN_DELIM}; virtual bool empty() const { return _tokens.empty(); } template 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 // requires std::ranges::view> template 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 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 R> R tokens() const { R r; if (_tokens.empty()) { return r; } std::ranges::copy(_tokens, std::back_inserter(r)); return r; } std::vector tokens() const { // return tokens>(); } protected: std::vector _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 class AdcKeyTokenNetMessage : public AdcTokenNetMessage { using base_t = AdcTokenNetMessage; 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 R keyBytes() const { R r; std::ranges::copy(this->_bytes, r); return r; } ByteStorageT keyBytes() const { // return this->_bytes; } template R keyView() const { // return R{this->_bytes.begin(), this->_bytes.end()}; } ByteViewT keyView() const { // return ByteViewT{this->_bytes.begin(), this->_bytes.end()}; } template 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 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