99.12% Lines (112/113) 94.12% Functions (16/17)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2026 Michael Vandeberg 2   // Copyright (c) 2026 Michael Vandeberg
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   /* 10   /*
11   Implementation type for the public buffer_slice() free function. 11   Implementation type for the public buffer_slice() free function.
12   Users see this only via auto + the Slice concept; the type is 12   Users see this only via auto + the Slice concept; the type is
13   documented as unspecified. Maintained alongside Slice in 13   documented as unspecified. Maintained alongside Slice in
14   include/boost/capy/concept/slice.hpp. 14   include/boost/capy/concept/slice.hpp.
15   */ 15   */
16   16  
17   #ifndef BOOST_CAPY_DETAIL_SLICE_IMPL_HPP 17   #ifndef BOOST_CAPY_DETAIL_SLICE_IMPL_HPP
18   #define BOOST_CAPY_DETAIL_SLICE_IMPL_HPP 18   #define BOOST_CAPY_DETAIL_SLICE_IMPL_HPP
19   19  
20   #include <boost/capy/detail/config.hpp> 20   #include <boost/capy/detail/config.hpp>
21   #include <boost/capy/buffers.hpp> 21   #include <boost/capy/buffers.hpp>
22   22  
23   #include <cstddef> 23   #include <cstddef>
24   #include <iterator> 24   #include <iterator>
25   #include <type_traits> 25   #include <type_traits>
26   26  
27   namespace boost { 27   namespace boost {
28   namespace capy { 28   namespace capy {
29   namespace detail { 29   namespace detail {
30   30  
31   template<class T> 31   template<class T>
32   struct slice_buffer_type_for; 32   struct slice_buffer_type_for;
33   33  
34   template<MutableBufferSequence T> 34   template<MutableBufferSequence T>
35   struct slice_buffer_type_for<T> 35   struct slice_buffer_type_for<T>
36   { 36   {
37   using type = mutable_buffer; 37   using type = mutable_buffer;
38   }; 38   };
39   39  
40   template<ConstBufferSequence T> 40   template<ConstBufferSequence T>
41   requires (!MutableBufferSequence<T>) 41   requires (!MutableBufferSequence<T>)
42   struct slice_buffer_type_for<T> 42   struct slice_buffer_type_for<T>
43   { 43   {
44   using type = const_buffer; 44   using type = const_buffer;
45   }; 45   };
46   46  
47   template<class BufferSequence> 47   template<class BufferSequence>
48   requires MutableBufferSequence<BufferSequence> 48   requires MutableBufferSequence<BufferSequence>
49   || ConstBufferSequence<BufferSequence> 49   || ConstBufferSequence<BufferSequence>
50   class slice_impl 50   class slice_impl
51   { 51   {
52   public: 52   public:
53   using iterator_type = 53   using iterator_type =
54   decltype(capy::begin(std::declval<BufferSequence const&>())); 54   decltype(capy::begin(std::declval<BufferSequence const&>()));
55   using end_iterator_type = 55   using end_iterator_type =
56   decltype(capy::end(std::declval<BufferSequence const&>())); 56   decltype(capy::end(std::declval<BufferSequence const&>()));
57   using buffer_type = 57   using buffer_type =
58   typename slice_buffer_type_for<BufferSequence>::type; 58   typename slice_buffer_type_for<BufferSequence>::type;
59   59  
60   private: 60   private:
61   iterator_type first_{}; 61   iterator_type first_{};
62   end_iterator_type last_{}; 62   end_iterator_type last_{};
63   std::size_t front_skip_ = 0; 63   std::size_t front_skip_ = 0;
64   std::size_t back_skip_ = 0; 64   std::size_t back_skip_ = 0;
65   65  
HITCBC 66   517 static buffer_type adjust_buffer( 66   42071 static buffer_type adjust_buffer(
67   buffer_type const& buf, 67   buffer_type const& buf,
68 - std::size_t front, 68 + std::size_t front_n,
69 - std::size_t back) noexcept 69 + std::size_t back_n) noexcept
70   { 70   {
71   if constexpr (std::is_same_v<buffer_type, mutable_buffer>) 71   if constexpr (std::is_same_v<buffer_type, mutable_buffer>)
72   { 72   {
HITCBC 73   257 return mutable_buffer( 73   18031 return mutable_buffer(
HITCBC 74 - 257 static_cast<char*>(buf.data()) + front, 74 + 18031 static_cast<char*>(buf.data()) + front_n,
HITCBC 75 - 514 buf.size() - front - back); 75 + 36062 buf.size() - front_n - back_n);
76   } 76   }
77   else 77   else
78   { 78   {
HITCBC 79   260 return const_buffer( 79   24040 return const_buffer(
HITCBC 80 - 260 static_cast<char const*>(buf.data()) + front, 80 + 24040 static_cast<char const*>(buf.data()) + front_n,
HITCBC 81 - 520 buf.size() - front - back); 81 + 48080 buf.size() - front_n - back_n);
82   } 82   }
83   } 83   }
84   84  
85   public: 85   public:
86   /// View returned by `slice_impl::data()`. 86   /// View returned by `slice_impl::data()`.
87   class data_view 87   class data_view
88   { 88   {
89   iterator_type first_{}; 89   iterator_type first_{};
90   end_iterator_type last_{}; 90   end_iterator_type last_{};
91   std::size_t front_skip_ = 0; 91   std::size_t front_skip_ = 0;
92   std::size_t back_skip_ = 0; 92   std::size_t back_skip_ = 0;
93   93  
94   public: 94   public:
95   class const_iterator 95   class const_iterator
96   { 96   {
97   iterator_type cur_{}; 97   iterator_type cur_{};
98   iterator_type anchor_first_{}; 98   iterator_type anchor_first_{};
99   end_iterator_type anchor_last_{}; 99   end_iterator_type anchor_last_{};
100   std::size_t front_skip_ = 0; 100   std::size_t front_skip_ = 0;
101   std::size_t back_skip_ = 0; 101   std::size_t back_skip_ = 0;
102   102  
103   public: 103   public:
104   using iterator_category = std::bidirectional_iterator_tag; 104   using iterator_category = std::bidirectional_iterator_tag;
105   using value_type = buffer_type; 105   using value_type = buffer_type;
106   using difference_type = std::ptrdiff_t; 106   using difference_type = std::ptrdiff_t;
107   using pointer = value_type*; 107   using pointer = value_type*;
108   using reference = value_type; 108   using reference = value_type;
109   109  
110   const_iterator() noexcept = default; 110   const_iterator() noexcept = default;
111   111  
HITCBC 112   978 const_iterator( 112   69754 const_iterator(
113   iterator_type cur, 113   iterator_type cur,
114   iterator_type anchor_first, 114   iterator_type anchor_first,
115   end_iterator_type anchor_last, 115   end_iterator_type anchor_last,
116   std::size_t front_skip, 116   std::size_t front_skip,
117   std::size_t back_skip) noexcept 117   std::size_t back_skip) noexcept
HITCBC 118   978 : cur_(cur) 118   69754 : cur_(cur)
HITCBC 119   978 , anchor_first_(anchor_first) 119   69754 , anchor_first_(anchor_first)
HITCBC 120   978 , anchor_last_(anchor_last) 120   69754 , anchor_last_(anchor_last)
HITCBC 121   978 , front_skip_(front_skip) 121   69754 , front_skip_(front_skip)
HITCBC 122   978 , back_skip_(back_skip) 122   69754 , back_skip_(back_skip)
123   { 123   {
HITCBC 124   978 } 124   69754 }
125   125  
HITCBC 126   624 bool operator==(const_iterator const& other) const noexcept 126   76234 bool operator==(const_iterator const& other) const noexcept
127   { 127   {
HITCBC 128   624 return cur_ == other.cur_; 128   76234 return cur_ == other.cur_;
129   } 129   }
130   130  
HITCBC 131   624 bool operator!=(const_iterator const& other) const noexcept 131   76234 bool operator!=(const_iterator const& other) const noexcept
132   { 132   {
HITCBC 133   624 return !(*this == other); 133   76234 return !(*this == other);
134   } 134   }
135   135  
HITCBC 136   517 value_type operator*() const noexcept 136   42071 value_type operator*() const noexcept
137   { 137   {
HITCBC 138   517 buffer_type buf = *cur_; 138   42071 buffer_type buf = *cur_;
HITCBC 139 - 517 auto front = (cur_ == anchor_first_) ? front_skip_ : 0; 139 + 42071 auto front_n = (cur_ == anchor_first_) ? front_skip_ : 0;
HITCBC 140   517 auto next = cur_; 140   42071 auto next = cur_;
HITCBC 141   517 ++next; 141   42071 ++next;
HITCBC 142 - 517 auto back = (next == anchor_last_) ? back_skip_ : 0; 142 + 42071 auto back_n = (next == anchor_last_) ? back_skip_ : 0;
HITCBC 143 - 517 return adjust_buffer(buf, front, back); 143 + 42071 return adjust_buffer(buf, front_n, back_n);
144   } 144   }
145   145  
HITCBC 146   487 const_iterator& operator++() noexcept 146   29897 const_iterator& operator++() noexcept
147   { 147   {
HITCBC 148   487 ++cur_; 148   29897 ++cur_;
HITCBC 149   487 return *this; 149   29897 return *this;
150   } 150   }
151   151  
HITCBC 152   274 const_iterator operator++(int) noexcept 152   6512 const_iterator operator++(int) noexcept
153   { 153   {
HITCBC 154   274 const_iterator tmp = *this; 154   6512 const_iterator tmp = *this;
HITCBC 155   274 ++*this; 155   6512 ++*this;
HITCBC 156   274 return tmp; 156   6512 return tmp;
157   } 157   }
158   158  
HITGIC 159   const_iterator& operator--() noexcept 159   12144 const_iterator& operator--() noexcept
160   { 160   {
HITGIC 161   --cur_; 161   12144 --cur_;
HITGIC 162   return *this; 162   12144 return *this;
163   } 163   }
164   164  
HITGIC 165   const_iterator operator--(int) noexcept 165   6072 const_iterator operator--(int) noexcept
166   { 166   {
HITGIC 167   const_iterator tmp = *this; 167   6072 const_iterator tmp = *this;
HITGIC 168   --*this; 168   6072 --*this;
HITGIC 169   return tmp; 169   6072 return tmp;
170   } 170   }
171   }; 171   };
172   172  
173   data_view() noexcept = default; 173   data_view() noexcept = default;
174   174  
HITCBC 175   283 data_view( 175   10692 data_view(
176   iterator_type first, 176   iterator_type first,
177   end_iterator_type last, 177   end_iterator_type last,
178   std::size_t front_skip, 178   std::size_t front_skip,
179   std::size_t back_skip) noexcept 179   std::size_t back_skip) noexcept
HITCBC 180   283 : first_(first) 180   10692 : first_(first)
HITCBC 181   283 , last_(last) 181   10692 , last_(last)
HITCBC 182   283 , front_skip_(front_skip) 182   10692 , front_skip_(front_skip)
HITCBC 183   283 , back_skip_(back_skip) 183   10692 , back_skip_(back_skip)
184   { 184   {
HITCBC 185   283 } 185   10692 }
186   186  
HITCBC 187   475 const_iterator begin() const noexcept 187   34863 const_iterator begin() const noexcept
188   { 188   {
189   return const_iterator( 189   return const_iterator(
HITCBC 190   475 first_, first_, last_, front_skip_, back_skip_); 190   34863 first_, first_, last_, front_skip_, back_skip_);
191   } 191   }
192   192  
HITCBC 193   503 const_iterator end() const noexcept 193   34891 const_iterator end() const noexcept
194   { 194   {
195   return const_iterator( 195   return const_iterator(
HITCBC 196   503 last_, first_, last_, front_skip_, back_skip_); 196   34891 last_, first_, last_, front_skip_, back_skip_);
197   } 197   }
198   }; 198   };
199   199  
MISUIC 200   slice_impl() noexcept = default; 200   slice_impl() noexcept = default;
201   201  
HITCBC 202   10 explicit slice_impl(BufferSequence const& bs) noexcept 202   10 explicit slice_impl(BufferSequence const& bs) noexcept
HITCBC 203   10 : first_(capy::begin(bs)) 203   10 : first_(capy::begin(bs))
HITCBC 204   10 , last_(capy::end(bs)) 204   10 , last_(capy::end(bs))
205   { 205   {
HITCBC 206   10 } 206   10 }
207   207  
HITCBC 208   225 slice_impl( 208   4377 slice_impl(
209   BufferSequence const& bs, 209   BufferSequence const& bs,
210   std::size_t offset, 210   std::size_t offset,
211   std::size_t length) noexcept 211   std::size_t length) noexcept
HITCBC 212   225 { 212   4377 {
HITCBC 213   225 auto it_begin = capy::begin(bs); 213   4377 auto it_begin = capy::begin(bs);
HITCBC 214   225 auto it_end = capy::end(bs); 214   4377 auto it_end = capy::end(bs);
215   215  
HITCBC 216   225 std::size_t total = 0; 216   4377 std::size_t total = 0;
HITCBC 217   544 for (auto it = it_begin; it != it_end; ++it) 217   10956 for (auto it = it_begin; it != it_end; ++it)
HITCBC 218   319 total += (*it).size(); 218   6579 total += (*it).size();
219   219  
HITCBC 220   225 if (offset > total) 220   4377 if (offset > total)
HITCBC 221   1 offset = total; 221   1 offset = total;
HITCBC 222   225 std::size_t const remaining = total - offset; 222   4377 std::size_t const remaining = total - offset;
HITCBC 223   225 if (length > remaining) 223   4377 if (length > remaining)
HITCBC 224   217 length = remaining; 224   2293 length = remaining;
225   225  
HITCBC 226   225 first_ = it_begin; 226   4377 first_ = it_begin;
HITCBC 227   225 last_ = it_end; 227   4377 last_ = it_end;
228   228  
HITCBC 229   225 std::size_t skip = offset; 229   4377 std::size_t skip = offset;
HITCBC 230   247 while (first_ != last_) 230   4756 while (first_ != last_)
231   { 231   {
HITCBC 232   240 std::size_t const buf_size = (*first_).size(); 232   4658 std::size_t const buf_size = (*first_).size();
HITCBC 233   240 if (skip < buf_size) 233   4658 if (skip < buf_size)
234   { 234   {
HITCBC 235   218 front_skip_ = skip; 235   4279 front_skip_ = skip;
HITCBC 236   218 break; 236   4279 break;
237   } 237   }
HITCBC 238   22 skip -= buf_size; 238   379 skip -= buf_size;
HITCBC 239   22 ++first_; 239   379 ++first_;
240   } 240   }
241   241  
HITCBC 242   225 std::size_t left = length; 242   4377 std::size_t left = length;
HITCBC 243   225 auto cursor = first_; 243   4377 auto cursor = first_;
HITCBC 244   225 std::size_t cursor_front = front_skip_; 244   4377 std::size_t cursor_front = front_skip_;
HITCBC 245   302 while (cursor != last_ && left > 0) 245   5734 while (cursor != last_ && left > 0)
246   { 246   {
HITCBC 247   294 std::size_t const buf_size = (*cursor).size(); 247   5358 std::size_t const buf_size = (*cursor).size();
HITCBC 248   294 std::size_t const avail = buf_size - cursor_front; 248   5358 std::size_t const avail = buf_size - cursor_front;
HITCBC 249   294 if (left <= avail) 249   5358 if (left <= avail)
250   { 250   {
HITCBC 251   217 back_skip_ = avail - left; 251   4001 back_skip_ = avail - left;
HITCBC 252   217 ++cursor; 252   4001 ++cursor;
HITCBC 253   217 last_ = cursor; 253   4001 last_ = cursor;
HITCBC 254   217 return; 254   4001 return;
255   } 255   }
HITCBC 256   77 left -= avail; 256   1357 left -= avail;
HITCBC 257   77 ++cursor; 257   1357 ++cursor;
HITCBC 258   77 cursor_front = 0; 258   1357 cursor_front = 0;
259   } 259   }
260   260  
HITCBC 261   8 last_ = cursor; 261   376 last_ = cursor;
262   } 262   }
263   263  
HITCBC 264   283 data_view data() const noexcept 264   10692 data_view data() const noexcept
265   { 265   {
HITCBC 266   283 return data_view(first_, last_, front_skip_, back_skip_); 266   10692 return data_view(first_, last_, front_skip_, back_skip_);
267   } 267   }
268   268  
HITCBC 269   180 void remove_prefix(std::size_t n) noexcept 269   746 void remove_prefix(std::size_t n) noexcept
270   { 270   {
HITCBC 271   204 while (n > 0 && first_ != last_) 271   1062 while (n > 0 && first_ != last_)
272   { 272   {
HITCBC 273   130 std::size_t const buf_total = (*first_).size(); 273   922 std::size_t const buf_total = (*first_).size();
HITCBC 274   130 std::size_t live = buf_total - front_skip_; 274   922 std::size_t live = buf_total - front_skip_;
HITCBC 275   130 auto next = first_; 275   922 auto next = first_;
HITCBC 276   130 ++next; 276   922 ++next;
HITCBC 277   130 bool const is_last = (next == last_); 277   922 bool const is_last = (next == last_);
HITCBC 278   130 if (is_last) 278   922 if (is_last)
HITCBC 279   96 live -= back_skip_; 279   406 live -= back_skip_;
280   280  
HITCBC 281   130 if (n < live) 281   922 if (n < live)
282   { 282   {
HITCBC 283   35 front_skip_ += n; 283   467 front_skip_ += n;
HITCBC 284   35 return; 284   471 return;
285   } 285   }
286   286  
HITCBC 287   95 n -= live; 287   455 n -= live;
HITCBC 288   95 if (is_last) 288   455 if (is_last)
289   { 289   {
HITCBC 290   71 first_ = last_; 290   139 first_ = last_;
HITCBC 291   71 front_skip_ = 0; 291   139 front_skip_ = 0;
HITCBC 292   71 back_skip_ = 0; 292   139 back_skip_ = 0;
HITCBC 293   71 return; 293   139 return;
294   } 294   }
HITCBC 295   24 ++first_; 295   316 ++first_;
HITCBC 296   24 front_skip_ = 0; 296   316 front_skip_ = 0;
297   } 297   }
298   } 298   }
299   }; 299   };
300   300  
301   } // namespace detail 301   } // namespace detail
302   } // namespace capy 302   } // namespace capy
303   } // namespace boost 303   } // namespace boost
304   304  
305   #endif 305   #endif