diff --git a/net/adc_netmsg.h b/net/adc_netmsg.h index 79f6d39..9184778 100644 --- a/net/adc_netmsg.h +++ b/net/adc_netmsg.h @@ -127,7 +127,8 @@ public: } bool emp = true; - for (const auto& el : _bytes) { + for (size_t i = _reservedNum; i < _bytes.size(); ++i) { + const auto& el = _bytes[i]; if (std::ranges::distance(el.begin(), el.end())) { emp = false; break; @@ -143,7 +144,7 @@ public: { R r; - for (size_t i = 0; i < _bytes.size(); ++i) { + for (size_t i = _reservedNum; i < _bytes.size(); ++i) { std::ranges::for_each(storageViewByIndex(i), [&r](const auto& el) { std::ranges::copy(el, std::back_inserter(r)); }); } @@ -152,7 +153,7 @@ public: } - virtual ByteStorageT bytes() const + ByteStorageT bytes() const { // return bytes(); @@ -165,7 +166,7 @@ public: R r; - for (size_t i = 0; i < _bytes.size(); ++i) { + for (size_t i = _reservedNum; i < _bytes.size(); ++i) { std::ranges::for_each(storageViewByIndex(i), [&r](const auto& el) { r.emplace_back(el.begin(), el.end()); }); } @@ -181,9 +182,14 @@ public: protected: std::vector _bytes; + size_t _reservedNum; - AdcNetMessageSeqInterface() = default; + AdcNetMessageSeqInterface(size_t reserved = 0) : _reservedNum(reserved), _bytes() + { + // reserve the "_reservedNum" first elements + _bytes.resize(_reservedNum); + } // return a sequence of storage element view and possible additional // byte views (e.g. elements delimiter) @@ -272,7 +278,7 @@ public: AdcTokenNetMessage() = default; template - AdcTokenNetMessage(const T& v, const Ts&... vs) : AdcTokenNetMessage() + AdcTokenNetMessage(const T& v, const Ts&... vs) : AdcTokenNetMessage() // _reservedNum = 0 { setTokens(v, vs...); } @@ -289,7 +295,8 @@ public: return r; } - std::ranges::copy(this->_bytes | std::views::drop(start) | std::views::take(N), std::back_inserter(r)); + std::ranges::copy(this->_bytes | std::views::drop(start + this->_reservedNum) | std::views::take(N), + std::back_inserter(r)); return r; } @@ -306,11 +313,12 @@ public: { R r; - if (empty() || (start >= this->_bytes.size()) || !N) { + if (empty() || (start >= _tokenNumber) || !N) { return r; } - utils::AdcJoinRange(this->_bytes | std::views::drop(start) | std::views::take(N), tokenDelimiter, r); + utils::AdcJoinRange(this->_bytes | std::views::drop(start + this->_reservedNum) | std::views::take(N), + tokenDelimiter, r); return r; } @@ -345,13 +353,16 @@ public: if constexpr (sizeof...(Ts)) { appendTokens(vs...); } + + _tokenNumber = this->_bytes.size() - this->_reservedNum; } template void setTokens(const T& v, const Ts&... vs) { - this->_bytes.clear(); + this->_bytes.resize(this->_reservedNum); + _tokenNumber = 0; appendTokens(v, vs...); } @@ -366,6 +377,8 @@ public: do { it = std::search(start_it, end, tokenDelimiter.begin(), tokenDelimiter.end()); std::copy(start_it, it, std::back_inserter(this->_bytes.emplace_back())); + ++_tokenNumber; + start_it = it; std::advance(start_it, tokenDelimiter.size()); // to support not only random-access iterators } while (it != end); @@ -376,19 +389,22 @@ public: void setFromBytes(IT begin, IT end) requires std::same_as, char> { - this->_bytes.clear(); + this->_bytes.resize(this->_reservedNum); + _tokenNumber = 0; appendFromBytes(begin, end); } protected: + size_t _tokenNumber; + virtual std::vector storageViewByIndex(size_t idx) const override { 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) && (_tokenNumber > 1)) { // add delimiter vw.emplace_back(tokenDelimiter.begin(), tokenDelimiter.end()); } @@ -421,29 +437,85 @@ public: using base_t::tokens; - AdcKeyTokenNetMessage() = default; + AdcKeyTokenNetMessage() + { + this->_reservedNum = 1; // reserve the first element for keyword + this->_bytes.resize(this->_reservedNum); + }; template - AdcKeyTokenNetMessage(const KT& key, const T& tok, const Ts&... toks) + AdcKeyTokenNetMessage(const KT& key, const T& tok, const Ts&... toks) : AdcKeyTokenNetMessage() { - utils::convertToBytes(this->_bytes.emplace_back(), key); + utils::convertToBytes(this->_bytes[0], key); setTokens(tok, toks...); } virtual ~AdcKeyTokenNetMessage() = default; + + // get a copy of message bytes + template + R bytes() const + { + R r; + + std::ranges::copy(this->_bytes[0], std::back_inserter(r)); // keyword + if (this->_tokenNumber) { + std::ranges::copy(keytokenDelimiter, std::back_inserter(r)); // keyword-to-token delimiter + } + + std::ranges::for_each(base_t::template bytesView(), [&r](const auto& el) { + std::ranges::copy(el, std::back_inserter(r)); // token + }); + + return r; + } + + + ByteStorageT bytes() const + { + // + return bytes(); + } + + // get a view of message bytes + template + R bytesView() const + { + R r; + + const auto& key = this->_bytes[0]; + std::back_inserter(r) = {key.begin(), key.end()}; // keyword + if (this->_tokenNumber) { + std::back_inserter(r) = {keytokenDelimiter.begin(), keytokenDelimiter.end()}; // keyword-to-token delimiter + } + + std::ranges::for_each(base_t::template bytesView(), [&r](const auto& el) { + std::back_inserter(r) = {el.begin(), el.end()}; // token + }); + + return r; + } + + std::vector bytesView() const + { + // + return bytesView>(); + } + template R keyBytes() const { R r; - if (empty()) { + const auto& key = this->_bytes[0]; + if (!std::distance(key.begin(), key.end())) { return r; } - std::ranges::copy(this->_bytes[0], r); + std::ranges::copy(key, std::back_inserter(r)); return r; } @@ -451,18 +523,16 @@ public: ByteStorageT keyBytes() const { - if (empty()) { - return ByteStorageT(); - } - - return this->_bytes[0]; + // + return keyBytes(); } template R keyView() const { - if (empty()) { + const auto& key = this->_bytes[0]; + if (!std::distance(key.begin(), key.end())) { return R(); } @@ -471,60 +541,20 @@ public: ByteViewT keyView() const - { - if (empty()) { - return ByteViewT(); - } - - return ByteViewT{this->_bytes[0].begin(), this->_bytes[0].end()}; - } - - template R> - R tokens(size_t start = 0, size_t N = std::numeric_limits::max()) const - { - // "+1" since the first element is keyword - return base_t::template tokens(start + 1, N); - } - - std::vector tokens(size_t start = 0, size_t N = std::numeric_limits::max()) const { // - return tokens>(start, N); + return keyView(); } - 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); - } - - - 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(); - - utils::convertToBytes(this->_bytes.emplace_back(), key); - appendTokens(tok, toks...); + setTokens(tok, toks...); + utils::convertToBytes(this->_bytes[0], key); } - template - void setTokens(const T& v, const Ts&... vs) - { - this->_bytes.resize(1); // the first element is keyword - - appendTokens(v, vs...); - } - template void setFromBytes(IT begin, IT end) @@ -541,23 +571,6 @@ public: 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]; - std::vector vw{{el.begin(), el.end()}}; - - if (this->_bytes.size() > 1) { // there are tokens, so add keyword-to-tokens delimiter - vw.emplace_back(keytokenDelimiter.begin(), keytokenDelimiter.end()); - } - - return vw; - } else { - return base_t::storageViewByIndex(idx); - } - } }; } // namespace adc diff --git a/tests/adc_netmsg_test.cpp b/tests/adc_netmsg_test.cpp index 432c9fe..ba67e97 100644 --- a/tests/adc_netmsg_test.cpp +++ b/tests/adc_netmsg_test.cpp @@ -36,9 +36,11 @@ TEST_CASE("[ADC NET MESSAGE]") } auto t2 = msg.bytesView(); + std::cout << "BYTES VIEW: "; for (auto& el : t2) { - std::cout << "BYTES VIEW: [" << el << "]\n"; + std::cout << "[" << el << "]"; } + std::cout << "\n"; std::cout << "\n\n---------\n\n"; @@ -47,7 +49,7 @@ 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 << "TOK BYTES: [" << msg.tokensBytes(1, 1) << "]\n"; std::cout << "\n\n---------\n\n"; @@ -59,9 +61,11 @@ TEST_CASE("[ADC NET MESSAGE]") tmsg.setFromBytes(bb.begin(), bb.end()); auto t1 = tmsg.bytesView(); + std::cout << "TOKENS VIEW: "; for (auto& el : t1) { - std::cout << "TOKEN VIEW: [" << el << "]\n"; + std::cout << "[" << el << "]"; } + std::cout << "\n"; } /*