TLA Line data Source code
1 : //
2 : // Copyright (c) 2026 Steve Gerbino
3 : // Copyright (c) 2026 Michael Vandeberg
4 : //
5 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 : //
8 : // Official repository: https://github.com/cppalliance/capy
9 : //
10 :
11 : #ifndef BOOST_CAPY_DETAIL_CONSUMING_BUFFERS_HPP
12 : #define BOOST_CAPY_DETAIL_CONSUMING_BUFFERS_HPP
13 :
14 : #include <boost/capy/detail/config.hpp>
15 : #include <boost/capy/buffers.hpp>
16 : #include <boost/capy/detail/slice_of.hpp>
17 :
18 : #include <cstddef>
19 : #include <utility>
20 :
21 : namespace boost {
22 : namespace capy {
23 : namespace detail {
24 :
25 : /** A cursor that drives consumption of a buffer sequence.
26 :
27 : `consuming_buffers` is the dedicated driver for `read_some`/`write_some`
28 : loops. It presents the not-yet-consumed bytes of a buffer sequence via
29 : `data()`, and `consume(n)` advances past `n` transferred bytes **in
30 : place**.
31 :
32 : It is deliberately **not** itself a buffer sequence — it hands out the
33 : remaining bytes through `data()` (returning a `slice_of` view). It
34 : **borrows** the underlying sequence (iterators + a consumed-byte offset).
35 : The sequence must outlive the cursor. That is the natural case when the
36 : cursor is a local of a composed operation that took its buffers by value.
37 : */
38 : template<class Seq>
39 : requires ConstBufferSequence<Seq>
40 : class consuming_buffers
41 : {
42 : public:
43 : /// Names the buffer type the underlying sequence `Seq` yields.
44 : using buffer_type = capy::buffer_type<Seq>;
45 :
46 : private:
47 : using iterator_type =
48 : decltype(capy::buffer_sequence_begin(std::declval<Seq const&>()));
49 :
50 : iterator_type first_{};
51 : iterator_type last_{};
52 : std::size_t front_skip_ = 0; // bytes consumed from *first_
53 :
54 : public:
55 : /** Construct a cursor over `s`.
56 :
57 : @param s The sequence to consume. Must outlive the cursor.
58 : */
59 HIT 306 : explicit consuming_buffers(Seq const& s) noexcept
60 306 : : first_(capy::buffer_sequence_begin(s))
61 306 : , last_(capy::buffer_sequence_end(s))
62 : {
63 306 : }
64 :
65 : /** Reject construction from a temporary (the view would dangle).
66 :
67 : @param s The sequence that would be consumed.
68 : */
69 : consuming_buffers(Seq const&& s) = delete;
70 :
71 : /** Return the remaining (unconsumed) bytes as a buffer sequence.
72 :
73 : @return The bytes not yet consumed, as a buffer sequence.
74 : */
75 : slice_of<Seq>
76 354 : data() const noexcept
77 : {
78 354 : return slice_of<Seq>(first_, last_, front_skip_, 0);
79 : }
80 :
81 : /** Discard `n` bytes from the front, in place.
82 :
83 : Advances past `min(n, remaining)` bytes.
84 :
85 : @param n The number of bytes consumed.
86 : */
87 : void
88 262 : consume(std::size_t n) noexcept
89 : {
90 387 : while (n > 0 && first_ != last_)
91 : {
92 199 : std::size_t const sz = buffer_type(*first_).size();
93 199 : std::size_t const avail = sz - front_skip_;
94 199 : if (n < avail)
95 : {
96 74 : front_skip_ += n;
97 74 : return;
98 : }
99 125 : n -= avail;
100 125 : ++first_;
101 125 : front_skip_ = 0;
102 : }
103 : }
104 : };
105 :
106 : /** Deduce the sequence type from the constructor argument.
107 :
108 : @tparam Seq The buffer sequence type.
109 : */
110 : template<class Seq>
111 : consuming_buffers(Seq const&) -> consuming_buffers<Seq>;
112 :
113 : } // namespace detail
114 : } // namespace capy
115 : } // namespace boost
116 :
117 : #endif
|