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