GCC Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 97.0% 128 / 0 / 132
Functions: 100.0% 24 / 0 / 24
Branches: 75.0% 24 / 0 / 32

libs/capy/include/boost/capy/buffers/consuming_buffers.hpp
Line Branch Exec Source
1 //
2 // Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com)
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
16 #include <cstddef>
17 #include <iterator>
18 #include <ranges>
19 #include <type_traits>
20
21 namespace boost {
22 namespace capy {
23
24 namespace detail {
25
26 template<class T>
27 struct buffer_type_for;
28
29 template<MutableBufferSequence T>
30 struct buffer_type_for<T>
31 {
32 using type = mutable_buffer;
33 };
34
35 template<ConstBufferSequence T>
36 requires (!MutableBufferSequence<T>)
37 struct buffer_type_for<T>
38 {
39 using type = const_buffer;
40 };
41
42 } // namespace detail
43
44 /** Wrapper for consuming a buffer sequence incrementally.
45
46 This class wraps a buffer sequence and tracks the current
47 position. It provides a `consume(n)` function that advances
48 through the sequence as bytes are processed.
49
50 Works with both mutable and const buffer sequences.
51
52 @tparam BufferSequence The buffer sequence type.
53 */
54 template<class BufferSequence>
55 requires MutableBufferSequence<BufferSequence> ||
56 ConstBufferSequence<BufferSequence>
57 class consuming_buffers
58 {
59 using iterator_type = decltype(capy::begin(std::declval<BufferSequence const&>()));
60 using end_iterator_type = decltype(capy::end(std::declval<BufferSequence const&>()));
61 using buffer_type = typename detail::buffer_type_for<BufferSequence>::type;
62
63 BufferSequence const& bufs_;
64 iterator_type it_;
65 end_iterator_type end_;
66 std::size_t consumed_ = 0; // Bytes consumed in current buffer
67
68 public:
69 /** Construct from a buffer sequence.
70
71 @param bufs The buffer sequence to wrap.
72 */
73 19 explicit consuming_buffers(BufferSequence const& bufs) noexcept
74 19 : bufs_(bufs)
75 19 , it_(capy::begin(bufs))
76 19 , end_(capy::end(bufs))
77 {
78 19 }
79
80 /** Consume n bytes from the buffer sequence.
81
82 Advances the current position by n bytes, moving to the
83 next buffer when the current one is exhausted.
84
85 @param n The number of bytes to consume.
86 */
87 29 void consume(std::size_t n) noexcept
88 {
89
12/16
boost::capy::consuming_buffers<boost::capy::const_buffer>::consume(unsigned long):
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
boost::capy::consuming_buffers<boost::capy::mutable_buffer>::consume(unsigned long):
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
boost::capy::consuming_buffers<std::array<boost::capy::const_buffer, 2ul> >::consume(unsigned long):
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
boost::capy::consuming_buffers<std::array<boost::capy::mutable_buffer, 2ul> >::consume(unsigned long):
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
58 while (n > 0 && it_ != end_)
90 {
91 29 auto const& buf = *it_;
92 29 std::size_t const buf_size = buf.size();
93 29 std::size_t const remaining = buf_size - consumed_;
94
95
6/8
boost::capy::consuming_buffers<boost::capy::const_buffer>::consume(unsigned long):
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 4 times.
boost::capy::consuming_buffers<boost::capy::mutable_buffer>::consume(unsigned long):
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
boost::capy::consuming_buffers<std::array<boost::capy::const_buffer, 2ul> >::consume(unsigned long):
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
boost::capy::consuming_buffers<std::array<boost::capy::mutable_buffer, 2ul> >::consume(unsigned long):
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
29 if (n < remaining)
96 {
97 // Consume part of current buffer
98 18 consumed_ += n;
99 18 n = 0;
100 }
101 else
102 {
103 // Consume rest of current buffer and move to next
104 11 n -= remaining;
105 11 consumed_ = 0;
106 11 ++it_;
107 }
108 }
109 29 }
110
111 /** Iterator for the consuming buffer sequence.
112
113 Returns buffers starting from the current position,
114 with the first buffer adjusted for consumed bytes.
115 */
116 class const_iterator
117 {
118 iterator_type it_;
119 end_iterator_type end_;
120 std::size_t consumed_;
121
122 public:
123 using iterator_category = std::bidirectional_iterator_tag;
124 using value_type = buffer_type;
125 using difference_type = std::ptrdiff_t;
126 using pointer = value_type*;
127 using reference = value_type;
128
129 // Default constructor required for forward_iterator
130 const_iterator() noexcept = default;
131
132 40 const_iterator(
133 iterator_type it,
134 end_iterator_type end,
135 std::size_t consumed) noexcept
136 40 : it_(it)
137 40 , end_(end)
138 40 , consumed_(consumed)
139 {
140 40 }
141
142 6 bool operator==(const_iterator const& other) const noexcept
143 {
144
6/8
boost::capy::consuming_buffers<boost::capy::mutable_buffer>::const_iterator::operator==(boost::capy::consuming_buffers<boost::capy::mutable_buffer>::const_iterator const&) const:
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
boost::capy::consuming_buffers<std::array<boost::capy::mutable_buffer, 2ul> >::const_iterator::operator==(boost::capy::consuming_buffers<std::array<boost::capy::mutable_buffer, 2ul> >::const_iterator const&) const:
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
6 return it_ == other.it_ && consumed_ == other.consumed_;
145 }
146
147 // != operator required for equality_comparable
148 6 bool operator!=(const_iterator const& other) const noexcept
149 {
150 6 return !(*this == other);
151 }
152
153 37 value_type operator*() const noexcept
154 {
155 37 auto const& buf = *it_;
156 if constexpr (std::is_same_v<buffer_type, mutable_buffer>)
157 {
158 48 return buffer_type(
159 16 static_cast<char*>(buf.data()) + consumed_,
160 32 buf.size() - consumed_);
161 }
162 else
163 {
164 63 return buffer_type(
165 21 static_cast<char const*>(buf.data()) + consumed_,
166 42 buf.size() - consumed_);
167 }
168 }
169
170 3 const_iterator& operator++() noexcept
171 {
172 3 consumed_ = 0;
173 3 ++it_;
174 3 return *this;
175 }
176
177 const_iterator operator++(int) noexcept
178 {
179 const_iterator tmp = *this;
180 ++*this;
181 return tmp;
182 }
183
184 const_iterator& operator--() noexcept
185 {
186 if (consumed_ == 0)
187 {
188 --it_;
189 // Set consumed_ to the size of the previous buffer
190 // This is a simplified implementation for bidirectional requirement
191 if (it_ != end_)
192 {
193 auto const& buf = *it_;
194 consumed_ = buf.size();
195 }
196 }
197 else
198 {
199 consumed_ = 0;
200 }
201 return *this;
202 }
203
204 const_iterator operator--(int) noexcept
205 {
206 const_iterator tmp = *this;
207 --*this;
208 return tmp;
209 }
210 };
211
212 /** Return iterator to beginning of remaining buffers.
213
214 @return Iterator pointing to the first remaining buffer,
215 adjusted for consumed bytes in the current buffer.
216 */
217 37 const_iterator begin() const noexcept
218 {
219 37 return const_iterator(it_, end_, consumed_);
220 }
221
222 /** Return iterator to end of buffer sequence.
223
224 @return End iterator.
225 */
226 3 const_iterator end() const noexcept
227 {
228 3 return const_iterator(end_, end_, 0);
229 }
230 };
231
232 } // namespace capy
233 } // namespace boost
234
235 #endif
236