#pragma once #include "../common/adc_traits.h" namespace adc { namespace traits { template concept adc_netproto_c = adc_range_of_view_char_range && requires(T t, const R& r) { { t.toLowLevel(r) } -> std::same_as; { t.fromLowLevel(r) } -> std::same_as; }; } // namespace traits namespace constants { static constexpr char ADC_DEFAULT_NETPROTO_STOPSEQ[] = "\n"; } // namespace constants template struct AdcNetProtoStopSeq : InetT { static constexpr std::string_view stopSeq = STOPSEQ; static constexpr size_t stopSeqSize = stopSeq.size(); using typename InetT::socket; /* range of char range's views */ template R toLowLevel(const R& r) { R res = r; // just add to the back of the range "stop sequence" element std::back_inserter(res) = {stopSeq.begin(), stopSeq.end()}; return res; } template R fromLowLevel(const R& r) { R res; auto N = std::distance(r.begin(), r.end()); if (!N) { return res; } // just remove the last element (it is assumed the last element is the stop sequence) std::ranges::copy(r | std::views::take(N - 1), std::back_inserter(res)); return res; } /* range of char */ template R toLowLevel(const R& r) { R res = r; // just add to the back of the "stop sequence" std::ranges::copy(stopSeq, std::back_inserter(res)); return res; } template R fromLowLevel(const R& r) { R res; auto N = std::distance(r.begin(), r.end()); if (N <= stopSeq) { // !!!!!!!!!!! return res; } // remove stopSeqSize bytes from the back of the input range std::ranges::copy(r | std::views::take(N - stopSeqSize), std::back_inserter(res)); return res; } /* from iterators to the input range */ template std::pair fromLowLevel(IT begin, IT end) { auto N = std::distance(begin, end); if (N <= stopSeqSize) { // !!!!!!!! return std::make_pair(end, end); } std::advance(end, -stopSeqSize); return std::make_pair(begin, end); } }; } // namespace adc