diff --git a/net/adc_netproto.h b/net/adc_netproto.h index 8fa5d9f..a56fe0f 100644 --- a/net/adc_netproto.h +++ b/net/adc_netproto.h @@ -22,16 +22,42 @@ namespace constants static constexpr char ADC_DEFAULT_NETPROTO_STOPSEQ[] = "\n"; +static constexpr char ADC_DEFAULT_NETPROTO_STARTMARK[] = "\n\t\r\v\r\t\n"; + } // namespace constants template struct AdcNetProtoStopSeq : InetT { - static constexpr std::string_view stopSeq = STOPSEQ; + static constexpr std::string_view stopSeq{STOPSEQ}; static constexpr size_t stopSeqSize = stopSeq.size(); + static_assert(stopSeqSize, "STOP BYTE SEQUENCE MUST NOT BE AN EMPTY ONE!!!"); + using typename InetT::socket; + template + std::pair matchCondition(IT begin, IT end) + { + auto res = std::make_pair(begin, false); + + if (begin == end) { + return res; + } + + res.first = std::search(begin, end, stopSeq.begin(), stopSeq.end()); + if (res.first != end) { + std::advance(res.first, stopSeqSize); // move iterator to the one-past-the-end position + res.second = true; + } else { + // may be only a part of message was received, + // so start next matching from previous begin-iterator + res.first = begin; + } + + return res; + } + /* range of char range's views */ template @@ -112,4 +138,51 @@ struct AdcNetProtoStopSeq : InetT { } }; + +template +struct AdcNetProtoSizedBlob { + static constexpr std::string_view startMark{START_MARK}; + static constexpr size_t sizeFieldLen = SIZE_FIELD_LEN; + + template + std::pair matchCondition(IT begin, IT end) + { + auto res = std::make_pair(begin, false); + + if (std::distance(begin, end) <= (startMark.size() + sizeFieldLen)) { // still unusefull part + return res; + } + + res.first = std::search(begin, end, startMark.begin(), startMark.end()); + if (res.first != end) { + std::advance(res.first, startMark); + auto it = res.first; + std::advance(it, sizeFieldLen); + + std::string sz_str{res.first, it}; + size_t blob_size = 0; + + auto end_ptr = sz_str.data() + sizeFieldLen; + auto [ptr, ec] = std::from_chars(sz_str.data(), end_ptr, blob_size, 16); // heximal!!! + if ((ec != std::errc()) || (ptr != end_ptr)) { + return {begin, false}; + } + + std::advance(res.first, sizeFieldLen); + if (std::distance(res.first, end) >= blob_size) { // still partially received message?! + std::advance(res.first, blob_size); // move output iterator to the one-past-the-end position + res.second = true; + } else { // still partially received message?! + res.first = begin; + } + } else { + // may be only a part of message was received, + // so start next matching from previous begin-iterator + res.first = begin; + } + + return res; + } +}; + } // namespace adc