0.00% Lines (0/0) 0.00% Functions (0/0)
TLA Baseline Branch
Line Hits Code Line Hits Code
1 - //  
2 - // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.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 - */  
DCB 73 - 215 explicit consuming_buffers(BufferSequence const& bufs) noexcept  
DCB 74 - 215 : bufs_(bufs)  
DCB 75 - 215 , it_(capy::begin(bufs))  
DCB 76 - 215 , end_(capy::end(bufs))  
77 - {  
DCB 78 - 215 }  
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 - */  
DCB 87 - 170 void consume(std::size_t n) noexcept  
88 - {  
DCB 89 - 290 while (n > 0 && it_ != end_)  
90 - {  
DCB 91 - 120 auto const& buf = *it_;  
DCB 92 - 120 std::size_t const buf_size = buf.size();  
DCB 93 - 120 std::size_t const remaining = buf_size - consumed_;  
94 -  
DCB 95 - 120 if (n < remaining)  
96 - {  
97 - // Consume part of current buffer  
DCB 98 - 30 consumed_ += n;  
DCB 99 - 30 n = 0;  
100 - }  
101 - else  
102 - {  
103 - // Consume rest of current buffer and move to next  
DCB 104 - 90 n -= remaining;  
DCB 105 - 90 consumed_ = 0;  
DCB 106 - 90 ++it_;  
107 - }  
108 - }  
DCB 109 - 170 }  
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 - /// Construct from position and consumed byte count.  
DCB 133 - 862 const_iterator(  
134 - iterator_type it,  
135 - end_iterator_type end,  
136 - std::size_t consumed) noexcept  
DCB 137 - 862 : it_(it)  
DCB 138 - 862 , end_(end)  
DCB 139 - 862 , consumed_(consumed)  
140 - {  
DCB 141 - 862 }  
142 -  
143 - /// Test for equality.  
DCB 144 - 544 bool operator==(const_iterator const& other) const noexcept  
145 - {  
DCB 146 - 544 return it_ == other.it_ && consumed_ == other.consumed_;  
147 - }  
148 -  
149 - /// Test for inequality.  
DCB 150 - 544 bool operator!=(const_iterator const& other) const noexcept  
151 - {  
DCB 152 - 544 return !(*this == other);  
153 - }  
154 -  
155 - /// Return the current buffer, adjusted for consumed bytes.  
DCB 156 - 481 value_type operator*() const noexcept  
157 - {  
DCB 158 - 481 auto const& buf = *it_;  
159 - if constexpr (std::is_same_v<buffer_type, mutable_buffer>)  
160 - {  
DCB 161 - 609 return buffer_type(  
DCB 162 - 203 static_cast<char*>(buf.data()) + consumed_,  
DCB 163 - 406 buf.size() - consumed_);  
164 - }  
165 - else  
166 - {  
DCB 167 - 834 return buffer_type(  
DCB 168 - 278 static_cast<char const*>(buf.data()) + consumed_,  
DCB 169 - 556 buf.size() - consumed_);  
170 - }  
171 - }  
172 -  
173 - /// Advance to the next element.  
DCB 174 - 451 const_iterator& operator++() noexcept  
175 - {  
DCB 176 - 451 consumed_ = 0;  
DCB 177 - 451 ++it_;  
DCB 178 - 451 return *this;  
179 - }  
180 -  
181 - /// Advance to the next element (postfix).  
DCB 182 - 286 const_iterator operator++(int) noexcept  
183 - {  
DCB 184 - 286 const_iterator tmp = *this;  
DCB 185 - 286 ++*this;  
DCB 186 - 286 return tmp;  
187 - }  
188 -  
189 - /// Move to the previous element.  
190 - const_iterator& operator--() noexcept  
191 - {  
192 - if (consumed_ == 0)  
193 - {  
194 - --it_;  
195 - // Set consumed_ to the size of the previous buffer  
196 - // This is a simplified implementation for bidirectional requirement  
197 - if (it_ != end_)  
198 - {  
199 - auto const& buf = *it_;  
200 - consumed_ = buf.size();  
201 - }  
202 - }  
203 - else  
204 - {  
205 - consumed_ = 0;  
206 - }  
207 - return *this;  
208 - }  
209 -  
210 - /// Move to the previous element (postfix).  
211 - const_iterator operator--(int) noexcept  
212 - {  
213 - const_iterator tmp = *this;  
214 - --*this;  
215 - return tmp;  
216 - }  
217 - };  
218 -  
219 - /** Return iterator to beginning of remaining buffers.  
220 -  
221 - @return Iterator pointing to the first remaining buffer,  
222 - adjusted for consumed bytes in the current buffer.  
223 - */  
DCB 224 - 431 const_iterator begin() const noexcept  
225 - {  
DCB 226 - 431 return const_iterator(it_, end_, consumed_);  
227 - }  
228 -  
229 - /** Return iterator to end of buffer sequence.  
230 -  
231 - @return End iterator.  
232 - */  
DCB 233 - 431 const_iterator end() const noexcept  
234 - {  
DCB 235 - 431 return const_iterator(end_, end_, 0);  
236 - }  
237 - };  
238 -  
239 - } // namespace capy  
240 - } // namespace boost  
241 -  
242 - #endif