96.15% Lines (25/26) 85.71% Functions (6/7)
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   // Copyright (c) 2026 Michael Vandeberg 3   // Copyright (c) 2026 Michael Vandeberg
4   // 4   //
5   // Distributed under the Boost Software License, Version 1.0. (See accompanying 5   // Distributed under the Boost Software License, Version 1.0. (See accompanying
6   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7   // 7   //
8   // Official repository: https://github.com/cppalliance/capy 8   // Official repository: https://github.com/cppalliance/capy
9   // 9   //
10   10  
11   #ifndef BOOST_CAPY_TEST_BUFGRIND_HPP 11   #ifndef BOOST_CAPY_TEST_BUFGRIND_HPP
12   #define BOOST_CAPY_TEST_BUFGRIND_HPP 12   #define BOOST_CAPY_TEST_BUFGRIND_HPP
13   13  
14   #include <boost/capy/detail/config.hpp> 14   #include <boost/capy/detail/config.hpp>
15   #include <boost/capy/buffers.hpp> 15   #include <boost/capy/buffers.hpp>
16 - #include <boost/capy/buffers/buffer_slice.hpp> 16 + #include <boost/capy/detail/slice_of.hpp>
17   #include <coroutine> 17   #include <coroutine>
18   #include <boost/capy/ex/await_context.hpp> 18   #include <boost/capy/ex/await_context.hpp>
19   19  
20   #include <algorithm> 20   #include <algorithm>
21   #include <cstddef> 21   #include <cstddef>
  22 + #include <limits>
22   #include <type_traits> 23   #include <type_traits>
23   #include <utility> 24   #include <utility>
24   25  
25   namespace boost { 26   namespace boost {
26   namespace capy { 27   namespace capy {
27   namespace test { 28   namespace test {
28   29  
29   /** Iterates split points of a buffer sequence into two adjacent halves. 30   /** Iterates split points of a buffer sequence into two adjacent halves.
30   31  
31   This class iterates through all possible ways to split a buffer 32   This class iterates through all possible ways to split a buffer
32   sequence into two parts (b1, b2) where concatenating them yields 33   sequence into two parts (b1, b2) where concatenating them yields
33   the original sequence. It uses an async-generator-like pattern 34   the original sequence. It uses an async-generator-like pattern
34   that allows `co_await` between iterations. 35   that allows `co_await` between iterations.
35   36  
36   The split type automatically preserves mutability: passing a 37   The split type automatically preserves mutability: passing a
37   `MutableBufferSequence` yields halves that model 38   `MutableBufferSequence` yields halves that model
38   @ref MutableBufferSequence, while passing a `ConstBufferSequence` 39   @ref MutableBufferSequence, while passing a `ConstBufferSequence`
39 - yields halves that model @ref ConstBufferSequence. Each half is 40 + yields halves that model @ref ConstBufferSequence. A single buffer
40 - the buffer-sequence view exposed by a @ref buffer_slice over the 41 + splits into two `mutable_buffer` or `const_buffer` values; any other
41 - corresponding byte range, and can be passed directly to 42 + sequence splits into two borrowed views. Either way each half can be
42 - `read_some`, `write_some`, `buffer_size`, etc. 43 + passed directly to `read_some`, `write_some`, `buffer_size`, etc.
43   44  
44   @par Thread Safety 45   @par Thread Safety
45   Not thread-safe. 46   Not thread-safe.
46   47  
47   @par Example 48   @par Example
48   @par !example example_1 49   @par !example example_1
49   50  
50   51  
51   @par Mutable Buffer Example 52   @par Mutable Buffer Example
52   @par !example example_2 53   @par !example example_2
53   54  
54   55  
55   @par Step Size Example 56   @par Step Size Example
56   @par !example example_3 57   @par !example example_3
57 -  
58 - @see @ref buffer_slice  
59   58  
60   */ 59   */
61   template<ConstBufferSequence BS> 60   template<ConstBufferSequence BS>
62   class bufgrind 61   class bufgrind
63   { 62   {
64   BS const& bs_; 63   BS const& bs_;
65   std::size_t size_; 64   std::size_t size_;
66   std::size_t step_; 65   std::size_t step_;
67   std::size_t pos_ = 0; 66   std::size_t pos_ = 0;
68   67  
69   public: 68   public:
70 - /// Names the buffer-sequence type `buffer_slice` yields for each half. 69 + /// Names the buffer-sequence type of each half.
71 - using slice_type = std::decay_t< 70 + using slice_type = std::conditional_t<
72 - decltype(buffer_slice(std::declval<BS const&>()))>; 71 + ConstBuffer<BS>,
  72 + buffer_type<BS>,
  73 + detail::slice_of<BS>>;
73   74  
74   /// Pairs the two `slice_type` halves that @ref next yields together. 75   /// Pairs the two `slice_type` halves that @ref next yields together.
75   using split_type = std::pair<slice_type, slice_type>; 76   using split_type = std::pair<slice_type, slice_type>;
76   77  
  78 + private:
  79 + static slice_type
HITGNC   80 + 396 slice(
  81 + BS const& bs,
  82 + std::size_t offset,
  83 + std::size_t length =
  84 + (std::numeric_limits<std::size_t>::max)()) noexcept
  85 + {
  86 + if constexpr (ConstBuffer<BS>)
  87 + {
HITGNC   88 + 382 slice_type b = bs;
HITGNC   89 + 382 b += offset;
HITGNC   90 + 382 if(length < b.size())
HITGNC   91 + 155 b = slice_type(b.data(), length);
HITGNC   92 + 382 return b;
  93 + }
  94 + else
  95 + {
HITGNC   96 + 14 return slice_type(bs, offset, length);
  97 + }
  98 + }
  99 +
  100 + public:
  101 +
77   /** Construct a buffer grinder. 102   /** Construct a buffer grinder.
78   103  
79   @param bs The buffer sequence to iterate over. 104   @param bs The buffer sequence to iterate over.
80   105  
81   @param step The number of bytes to advance on each call to 106   @param step The number of bytes to advance on each call to
82   @ref next. A value of 0 is treated as 1. The final split 107   @ref next. A value of 0 is treated as 1. The final split
83   at `buffer_size( bs )` is always included regardless of 108   at `buffer_size( bs )` is always included regardless of
84   step alignment. 109   step alignment.
85   */ 110   */
86   explicit 111   explicit
HITCBC 87   39 bufgrind( 112   39 bufgrind(
88   BS const& bs, 113   BS const& bs,
89   std::size_t step = 1) noexcept 114   std::size_t step = 1) noexcept
HITCBC 90   39 : bs_(bs) 115   39 : bs_(bs)
HITCBC 91   39 , size_(buffer_size(bs)) 116   39 , size_(buffer_size(bs))
HITCBC 92   39 , step_(step > 0 ? step : 1) 117   39 , step_(step > 0 ? step : 1)
93   { 118   {
HITCBC 94   39 } 119   39 }
95   120  
96   /** Check if more split points remain. 121   /** Check if more split points remain.
97   122  
98   @return `true` if @ref next can be called, `false` otherwise. 123   @return `true` if @ref next can be called, `false` otherwise.
99   */ 124   */
HITCBC 100   237 explicit operator bool() const noexcept 125   237 explicit operator bool() const noexcept
101   { 126   {
HITCBC 102   237 return pos_ <= size_; 127   237 return pos_ <= size_;
103   } 128   }
104   129  
105   /** Computes the current split synchronously, so awaiting it never suspends the caller. 130   /** Computes the current split synchronously, so awaiting it never suspends the caller.
106   */ 131   */
107   struct next_awaitable 132   struct next_awaitable
108   { 133   {
109   /// The grinder that produced this awaitable. 134   /// The grinder that produced this awaitable.
110   bufgrind* self_; 135   bufgrind* self_;
111   136  
112   /** Report whether the awaitable is ready. 137   /** Report whether the awaitable is ready.
113   138  
114   @return `true` always; the split is available without suspending. 139   @return `true` always; the split is available without suspending.
115   */ 140   */
HITCBC 116   198 bool await_ready() const noexcept { return true; } 141   198 bool await_ready() const noexcept { return true; }
117   142  
118   /** Resume the caller inline without suspending. 143   /** Resume the caller inline without suspending.
119   144  
120   @param h The awaiting coroutine handle. 145   @param h The awaiting coroutine handle.
121   146  
122   @return @p h, so the caller resumes immediately. 147   @return @p h, so the caller resumes immediately.
123   */ 148   */
MISUBC 124   ✗ std::coroutine_handle<> await_suspend(std::coroutine_handle<> h, await_context const*) const noexcept { return h; } 149   ✗ std::coroutine_handle<> await_suspend(std::coroutine_handle<> h, await_context const*) const noexcept { return h; }
125   150  
126   /** Return the current split and advance to the next. 151   /** Return the current split and advance to the next.
127   152  
128   @return The `(b1, b2)` split at the current position. 153   @return The `(b1, b2)` split at the current position.
129   */ 154   */
130   split_type 155   split_type
HITCBC 131   198 await_resume() 156   198 await_resume()
132   { 157   {
HITCBC 133   198 split_type result{ 158   198 split_type result{
HITCBC 134 - 198 buffer_slice(self_->bs_, 0, self_->pos_), 159 + 198 slice(self_->bs_, 0, self_->pos_),
HITCBC 135 - 198 buffer_slice(self_->bs_, self_->pos_) 160 + 198 slice(self_->bs_, self_->pos_)
136   }; 161   };
HITCBC 137   198 if(self_->pos_ < self_->size_) 162   198 if(self_->pos_ < self_->size_)
HITCBC 138   161 self_->pos_ = (std::min)(self_->pos_ + self_->step_, self_->size_); 163   161 self_->pos_ = (std::min)(self_->pos_ + self_->step_, self_->size_);
139   else 164   else
HITCBC 140   37 ++self_->pos_; 165   37 ++self_->pos_;
HITCBC 141   198 return result; 166   198 return result;
142   } 167   }
143   }; 168   };
144   169  
145   /** Return the next split point. 170   /** Return the next split point.
146   171  
147   Returns an awaitable that yields the current (b1, b2) pair 172   Returns an awaitable that yields the current (b1, b2) pair
148   and advances to the next split point. 173   and advances to the next split point.
149   174  
150   @par Preconditions 175   @par Preconditions
151   `static_cast<bool>( *this )` is `true`. 176   `static_cast<bool>( *this )` is `true`.
152   177  
153   @return An awaitable that await-returns `split_type`. 178   @return An awaitable that await-returns `split_type`.
154   */ 179   */
155   next_awaitable 180   next_awaitable
HITCBC 156   198 next() noexcept 181   198 next() noexcept
157   { 182   {
HITCBC 158   198 return {this}; 183   198 return {this};
159   } 184   }
160   }; 185   };
161   186  
162   } // test 187   } // test
163   } // capy 188   } // capy
164   } // boost 189   } // boost
165   190  
166   #endif 191   #endif