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   42071 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_n, 68   std::size_t front_n,
69   std::size_t back_n) 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   18031 return mutable_buffer( 73   18031 return mutable_buffer(
HITCBC 74   18031 static_cast<char*>(buf.data()) + front_n, 74   18031 static_cast<char*>(buf.data()) + front_n,
HITCBC 75   36062 buf.size() - front_n - back_n); 75   36062 buf.size() - front_n - back_n);
76   } 76   }
77   else 77   else
78   { 78   {
HITCBC 79   24040 return const_buffer( 79   24040 return const_buffer(
HITCBC 80   24040 static_cast<char const*>(buf.data()) + front_n, 80   24040 static_cast<char const*>(buf.data()) + front_n,
HITCBC 81   48080 buf.size() - front_n - back_n); 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   69754 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   69754 : cur_(cur) 118   69754 : cur_(cur)
HITCBC 119   69754 , anchor_first_(anchor_first) 119   69754 , anchor_first_(anchor_first)
HITCBC 120   69754 , anchor_last_(anchor_last) 120   69754 , anchor_last_(anchor_last)
HITCBC 121   69754 , front_skip_(front_skip) 121   69754 , front_skip_(front_skip)
HITCBC 122   69754 , back_skip_(back_skip) 122   69754 , back_skip_(back_skip)
123   { 123   {
HITCBC 124   69754 } 124   69754 }
125   125  
HITCBC 126   76234 bool operator==(const_iterator const& other) const noexcept 126   76234 bool operator==(const_iterator const& other) const noexcept
127   { 127   {
HITCBC 128   76234 return cur_ == other.cur_; 128   76234 return cur_ == other.cur_;
129   } 129   }
130   130  
HITCBC 131   76234 bool operator!=(const_iterator const& other) const noexcept 131   76234 bool operator!=(const_iterator const& other) const noexcept
132   { 132   {
HITCBC 133   76234 return !(*this == other); 133   76234 return !(*this == other);
134   } 134   }
135   135  
HITCBC 136   42071 value_type operator*() const noexcept 136   42071 value_type operator*() const noexcept
137   { 137   {
HITCBC 138   42071 buffer_type buf = *cur_; 138   42071 buffer_type buf = *cur_;
HITCBC 139   42071 auto front_n = (cur_ == anchor_first_) ? front_skip_ : 0; 139   42071 auto front_n = (cur_ == anchor_first_) ? front_skip_ : 0;
HITCBC 140   42071 auto next = cur_; 140   42071 auto next = cur_;
HITCBC 141   42071 ++next; 141   42071 ++next;
HITCBC 142   42071 auto back_n = (next == anchor_last_) ? back_skip_ : 0; 142   42071 auto back_n = (next == anchor_last_) ? back_skip_ : 0;
HITCBC 143   42071 return adjust_buffer(buf, front_n, back_n); 143   42071 return adjust_buffer(buf, front_n, back_n);
144   } 144   }
145   145  
HITCBC 146   29897 const_iterator& operator++() noexcept 146   29897 const_iterator& operator++() noexcept
147   { 147   {
HITCBC 148   29897 ++cur_; 148   29897 ++cur_;
HITCBC 149   29897 return *this; 149   29897 return *this;
150   } 150   }
151   151  
HITCBC 152   6512 const_iterator operator++(int) noexcept 152   6512 const_iterator operator++(int) noexcept
153   { 153   {
HITCBC 154   6512 const_iterator tmp = *this; 154   6512 const_iterator tmp = *this;
HITCBC 155   6512 ++*this; 155   6512 ++*this;
HITCBC 156   6512 return tmp; 156   6512 return tmp;
157   } 157   }
158   158  
HITCBC 159   12144 const_iterator& operator--() noexcept 159   12144 const_iterator& operator--() noexcept
160   { 160   {
HITCBC 161   12144 --cur_; 161   12144 --cur_;
HITCBC 162   12144 return *this; 162   12144 return *this;
163   } 163   }
164   164  
HITCBC 165   6072 const_iterator operator--(int) noexcept 165   6072 const_iterator operator--(int) noexcept
166   { 166   {
HITCBC 167   6072 const_iterator tmp = *this; 167   6072 const_iterator tmp = *this;
HITCBC 168   6072 --*this; 168   6072 --*this;
HITCBC 169   6072 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   10692 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   10692 : first_(first) 180   10692 : first_(first)
HITCBC 181   10692 , last_(last) 181   10692 , last_(last)
HITCBC 182   10692 , front_skip_(front_skip) 182   10692 , front_skip_(front_skip)
HITCBC 183   10692 , back_skip_(back_skip) 183   10692 , back_skip_(back_skip)
184   { 184   {
HITCBC 185   10692 } 185   10692 }
186   186  
HITCBC 187   34863 const_iterator begin() const noexcept 187   34863 const_iterator begin() const noexcept
188   { 188   {
189   return const_iterator( 189   return const_iterator(
HITCBC 190   34863 first_, first_, last_, front_skip_, back_skip_); 190   34863 first_, first_, last_, front_skip_, back_skip_);
191   } 191   }
192   192  
HITCBC 193   34891 const_iterator end() const noexcept 193   34891 const_iterator end() const noexcept
194   { 194   {
195   return const_iterator( 195   return const_iterator(
HITCBC 196   34891 last_, first_, last_, front_skip_, back_skip_); 196   34891 last_, first_, last_, front_skip_, back_skip_);
197   } 197   }
198   }; 198   };
199   199  
MISUBC 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   4377 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   4377 { 212   4377 {
HITCBC 213   4377 auto it_begin = capy::begin(bs); 213   4377 auto it_begin = capy::begin(bs);
HITCBC 214   4377 auto it_end = capy::end(bs); 214   4377 auto it_end = capy::end(bs);
215   215  
HITCBC 216   4377 std::size_t total = 0; 216   4377 std::size_t total = 0;
HITCBC 217   10956 for (auto it = it_begin; it != it_end; ++it) 217   10956 for (auto it = it_begin; it != it_end; ++it)
HITCBC 218   6579 total += (*it).size(); 218   6579 total += (*it).size();
219   219  
HITCBC 220   4377 if (offset > total) 220   4377 if (offset > total)
HITCBC 221   1 offset = total; 221   1 offset = total;
HITCBC 222   4377 std::size_t const remaining = total - offset; 222   4377 std::size_t const remaining = total - offset;
HITCBC 223   4377 if (length > remaining) 223   4377 if (length > remaining)
HITCBC 224   2293 length = remaining; 224   2293 length = remaining;
225   225  
HITCBC 226   4377 first_ = it_begin; 226   4377 first_ = it_begin;
HITCBC 227   4377 last_ = it_end; 227   4377 last_ = it_end;
228   228  
HITCBC 229   4377 std::size_t skip = offset; 229   4377 std::size_t skip = offset;
HITCBC 230   4756 while (first_ != last_) 230   4756 while (first_ != last_)
231   { 231   {
HITCBC 232   4658 std::size_t const buf_size = (*first_).size(); 232   4658 std::size_t const buf_size = (*first_).size();
HITCBC 233   4658 if (skip < buf_size) 233   4658 if (skip < buf_size)
234   { 234   {
HITCBC 235   4279 front_skip_ = skip; 235   4279 front_skip_ = skip;
HITCBC 236   4279 break; 236   4279 break;
237   } 237   }
HITCBC 238   379 skip -= buf_size; 238   379 skip -= buf_size;
HITCBC 239   379 ++first_; 239   379 ++first_;
240   } 240   }
241   241  
HITCBC 242   4377 std::size_t left = length; 242   4377 std::size_t left = length;
HITCBC 243   4377 auto cursor = first_; 243   4377 auto cursor = first_;
HITCBC 244   4377 std::size_t cursor_front = front_skip_; 244   4377 std::size_t cursor_front = front_skip_;
HITCBC 245   5734 while (cursor != last_ && left > 0) 245   5734 while (cursor != last_ && left > 0)
246   { 246   {
HITCBC 247   5358 std::size_t const buf_size = (*cursor).size(); 247   5358 std::size_t const buf_size = (*cursor).size();
HITCBC 248   5358 std::size_t const avail = buf_size - cursor_front; 248   5358 std::size_t const avail = buf_size - cursor_front;
HITCBC 249   5358 if (left <= avail) 249   5358 if (left <= avail)
250   { 250   {
HITCBC 251   4001 back_skip_ = avail - left; 251   4001 back_skip_ = avail - left;
HITCBC 252   4001 ++cursor; 252   4001 ++cursor;
HITCBC 253   4001 last_ = cursor; 253   4001 last_ = cursor;
HITCBC 254   4001 return; 254   4001 return;
255   } 255   }
HITCBC 256   1357 left -= avail; 256   1357 left -= avail;
HITCBC 257   1357 ++cursor; 257   1357 ++cursor;
HITCBC 258   1357 cursor_front = 0; 258   1357 cursor_front = 0;
259   } 259   }
260   260  
HITCBC 261   376 last_ = cursor; 261   376 last_ = cursor;
262   } 262   }
263   263  
HITCBC 264   10692 data_view data() const noexcept 264   10692 data_view data() const noexcept
265   { 265   {
HITCBC 266   10692 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   746 void remove_prefix(std::size_t n) noexcept 269   746 void remove_prefix(std::size_t n) noexcept
270   { 270   {
HITCBC 271   1062 while (n > 0 && first_ != last_) 271   1062 while (n > 0 && first_ != last_)
272   { 272   {
HITCBC 273   922 std::size_t const buf_total = (*first_).size(); 273   922 std::size_t const buf_total = (*first_).size();
HITCBC 274   922 std::size_t live = buf_total - front_skip_; 274   922 std::size_t live = buf_total - front_skip_;
HITCBC 275   922 auto next = first_; 275   922 auto next = first_;
HITCBC 276   922 ++next; 276   922 ++next;
HITCBC 277   922 bool const is_last = (next == last_); 277   922 bool const is_last = (next == last_);
HITCBC 278   922 if (is_last) 278   922 if (is_last)
HITCBC 279   406 live -= back_skip_; 279   406 live -= back_skip_;
280   280  
HITCBC 281   922 if (n < live) 281   922 if (n < live)
282   { 282   {
HITCBC 283   467 front_skip_ += n; 283   467 front_skip_ += n;
HITCBC 284   471 return; 284   471 return;
285   } 285   }
286   286  
HITCBC 287   455 n -= live; 287   455 n -= live;
HITCBC 288   455 if (is_last) 288   455 if (is_last)
289   { 289   {
HITCBC 290   139 first_ = last_; 290   139 first_ = last_;
HITCBC 291   139 front_skip_ = 0; 291   139 front_skip_ = 0;
HITCBC 292   139 back_skip_ = 0; 292   139 back_skip_ = 0;
HITCBC 293   139 return; 293   139 return;
294   } 294   }
HITCBC 295   316 ++first_; 295   316 ++first_;
HITCBC 296   316 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