include/boost/capy/buffers/consuming_buffers.hpp

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