From cf543feeb5c51c6734f6498a6760066ce96aa47d Mon Sep 17 00:00:00 2001 From: "Timur A. Fatkhullin" Date: Wed, 5 Jun 2024 09:35:39 +0300 Subject: [PATCH] ... --- CMakeLists.txt | 3 +- common/adc_utils.h | 2 +- net/adc_netmsg.h | 127 ++++++++++++++++++++++++-------------- tests/adc_netmsg_test.cpp | 3 + 4 files changed, 86 insertions(+), 49 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d9509b..0c004aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,8 @@ set(ADC_DEVICE_HEADERS set(ADC_NETWORK_HEADERS - net/adc_netmessage.h + net/adc_netmsg.h + # net/adc_netmessage.h net/adc_netproto.h net/adc_netservice.h ) diff --git a/common/adc_utils.h b/common/adc_utils.h index 5ede0a2..b42f1f2 100644 --- a/common/adc_utils.h +++ b/common/adc_utils.h @@ -448,7 +448,7 @@ public: template > RO> -static size_t AdcJoinRange(R& r, const RD& delim, RO& ro) +static size_t AdcJoinRange(const R& r, const RD& delim, RO& ro) requires std::ranges::range> && // input R is range of ranges std::same_as>, std::ranges::range_value_t> { diff --git a/net/adc_netmsg.h b/net/adc_netmsg.h index 8acd495..79f6d39 100644 --- a/net/adc_netmsg.h +++ b/net/adc_netmsg.h @@ -13,13 +13,14 @@ namespace adc { -namespace utils { - - -template -void convertToBytes(ByteStorageT &res, const T &v, const Ts &...vs) +namespace utils { - if constexpr (std::is_array_v>) { // to handle with trailing '\0' in plain char array + + +template +void convertToBytes(ByteStorageT& res, const T& v, const Ts&... vs) +{ + if constexpr (std::is_array_v>) { // to handle with trailing '\0' in plain char array convertToBytes(res, std::string_view(v), vs...); } else { if constexpr (traits::adc_input_char_range) { @@ -39,36 +40,36 @@ void convertToBytes(ByteStorageT &res, const T &v, const Ts &...vs) } -} // namespace utils +} // namespace utils -namespace traits { +namespace traits +{ -template -concept adc_netmessage_c = requires(const T t) { // const methods +template +concept adc_netmessage_c = requires(const T t) { // const methods { t.empty() } -> std::convertible_to; { t.bytes() } -> adc_output_char_range; { t.byteView() } -> adc_range_of_view_char_range; }; -} // namespace traits +} // namespace traits /* Trivial message interface: byte storage: just a char-range */ -template +template class AdcNetMessageTrivialInterface { public: - virtual ~AdcNetMessageTrivialInterface() = default; bool empty() const { return std::ranges::distance(_bytes.begin(), _bytes.end()) == 0; } // get a copy of message bytes - template + template R bytes() const { R r; @@ -85,7 +86,7 @@ public: } // get a view of message bytes - template + template R bytesView() const { R r; @@ -113,7 +114,7 @@ protected: interface for more complex messages: byte storage: std::vector of char-range (sequence of buffers) */ -template +template class AdcNetMessageSeqInterface { public: @@ -126,7 +127,7 @@ public: } bool emp = true; - for (const auto &el : _bytes) { + for (const auto& el : _bytes) { if (std::ranges::distance(el.begin(), el.end())) { emp = false; break; @@ -137,14 +138,14 @@ public: } // get a copy of message bytes - template + template R bytes() const { R r; for (size_t i = 0; i < _bytes.size(); ++i) { std::ranges::for_each(storageViewByIndex(i), - [&r](const auto &el) { std::ranges::copy(el, std::back_inserter(r)); }); + [&r](const auto& el) { std::ranges::copy(el, std::back_inserter(r)); }); } return r; @@ -158,14 +159,15 @@ public: } // get a view of message bytes - template + template R bytesView() const { R r; for (size_t i = 0; i < _bytes.size(); ++i) { - std::ranges::for_each(storageViewByIndex(i), [&r](const auto &el) { r.emplace_back(el.begin(), el.end()); }); + std::ranges::for_each(storageViewByIndex(i), + [&r](const auto& el) { r.emplace_back(el.begin(), el.end()); }); } return r; @@ -190,9 +192,6 @@ protected: - - - // Generic message class template class AdcGenericNetMessage : public AdcNetMessageTrivialInterface @@ -206,8 +205,8 @@ public: using base_t::empty; - template - AdcGenericNetMessage(const T &v, const Ts &...vs) : AdcGenericNetMessage() + template + AdcGenericNetMessage(const T& v, const Ts&... vs) : AdcGenericNetMessage() { appendBytes(v, vs...); } @@ -266,8 +265,8 @@ class AdcTokenNetMessage : public AdcNetMessageSeqInterface + R tokensBytes(size_t start = 0, size_t N = std::numeric_limits::max()) const + { + R r; + + if (empty() || (start >= this->_bytes.size()) || !N) { + return r; + } + + utils::AdcJoinRange(this->_bytes | std::views::drop(start) | std::views::take(N), tokenDelimiter, r); + + return r; + } + + + ByteStorageT tokensBytes(size_t start = 0, size_t N = std::numeric_limits::max()) const + { + return tokensBytes(start, N); + } + + template void appendTokens(const T& v, const Ts&... vs) { @@ -347,7 +367,7 @@ public: it = std::search(start_it, end, tokenDelimiter.begin(), tokenDelimiter.end()); std::copy(start_it, it, std::back_inserter(this->_bytes.emplace_back())); start_it = it; - std::advance(start_it, tokenDelimiter.size()); // to support not only random-access iterators + std::advance(start_it, tokenDelimiter.size()); // to support not only random-access iterators } while (it != end); } @@ -364,11 +384,11 @@ public: protected: virtual std::vector storageViewByIndex(size_t idx) const override { - const ByteStorageT &el = this->_bytes[idx]; + const ByteStorageT& el = this->_bytes[idx]; std::vector vw{{el.begin(), el.end()}}; auto last_idx = this->_bytes.size() - 1; - if (idx < last_idx) { // add delimiter + if (idx < last_idx) { // add delimiter vw.emplace_back(tokenDelimiter.begin(), tokenDelimiter.end()); } @@ -392,20 +412,20 @@ class AdcKeyTokenNetMessage : public AdcTokenNetMessage - AdcKeyTokenNetMessage(const KT &key, const T &tok, const Ts &...toks) + template + AdcKeyTokenNetMessage(const KT& key, const T& tok, const Ts&... toks) { utils::convertToBytes(this->_bytes.emplace_back(), key); setTokens(tok, toks...); @@ -459,7 +479,7 @@ public: return ByteViewT{this->_bytes[0].begin(), this->_bytes[0].end()}; } - template R> + template R> R tokens(size_t start = 0, size_t N = std::numeric_limits::max()) const { // "+1" since the first element is keyword @@ -472,9 +492,23 @@ public: return tokens>(start, N); } + template + R tokensBytes(size_t start = 0, size_t N = std::numeric_limits::max()) const + { + // "+1" since the first element is keyword + return base_t::template tokensBytes(start + 1, N); + } - template - void setKeyTokens(const KT &key, const T &tok, const Ts &...toks) + + ByteStorageT tokensBytes(size_t start = 0, size_t N = std::numeric_limits::max()) const + { + return tokensBytes(start, N); + } + + + + template + void setKeyTokens(const KT& key, const T& tok, const Ts&... toks) { this->_bytes.clear(); @@ -486,13 +520,13 @@ public: template void setTokens(const T& v, const Ts&... vs) { - this->_bytes.resize(1); // the first element is keyword + this->_bytes.resize(1); // the first element is keyword appendTokens(v, vs...); } - template + template void setFromBytes(IT begin, IT end) requires std::same_as, char> { @@ -500,23 +534,22 @@ public: auto it = std::search(begin, end, keytokenDelimiter.begin(), keytokenDelimiter.end()); - std::copy(begin, it, std::back_inserter(this->_bytes.emplace_back())); // keyword + std::copy(begin, it, std::back_inserter(this->_bytes.emplace_back())); // keyword if (it != end) { std::advance(it, keytokenDelimiter.size()); - appendFromBytes(it, end); // tokens + appendFromBytes(it, end); // tokens } } protected: - virtual std::vector storageViewByIndex(size_t idx) const override { - if (idx == 0) { // the first element is keyword - const ByteStorageT &el = this->_bytes[idx]; + if (idx == 0) { // the first element is keyword + const ByteStorageT& el = this->_bytes[idx]; std::vector vw{{el.begin(), el.end()}}; - if (this->_bytes.size() > 1) { // there are tokens, so add keyword-to-tokens delimiter + if (this->_bytes.size() > 1) { // there are tokens, so add keyword-to-tokens delimiter vw.emplace_back(keytokenDelimiter.begin(), keytokenDelimiter.end()); } diff --git a/tests/adc_netmsg_test.cpp b/tests/adc_netmsg_test.cpp index 610e583..432c9fe 100644 --- a/tests/adc_netmsg_test.cpp +++ b/tests/adc_netmsg_test.cpp @@ -47,6 +47,9 @@ TEST_CASE("[ADC NET MESSAGE]") msg.setTokens("FILTER", "A1", "B3"); std::cout << "BYTES: " << msg.bytes() << "\n"; + std::cout << "TOK BYTES: " << msg.tokensBytes(1, 1) << "\n"; + + std::cout << "\n\n---------\n\n";