100.00% Lines (7/7) 100.00% Functions (1/1)
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   #ifndef BOOST_CAPY_BUFFERS_BUFFER_SLICE_HPP 10   #ifndef BOOST_CAPY_BUFFERS_BUFFER_SLICE_HPP
11   #define BOOST_CAPY_BUFFERS_BUFFER_SLICE_HPP 11   #define BOOST_CAPY_BUFFERS_BUFFER_SLICE_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   #include <boost/capy/detail/slice_of.hpp> 15   #include <boost/capy/detail/slice_of.hpp>
16   16  
17   #include <concepts> 17   #include <concepts>
18   #include <cstddef> 18   #include <cstddef>
19   #include <limits> 19   #include <limits>
20   #include <type_traits> 20   #include <type_traits>
21   21  
22   namespace boost { 22   namespace boost {
23   namespace capy { 23   namespace capy {
24   24  
25   /** The type produced by `buffer_slice` for a sequence `BS`. 25   /** The type produced by `buffer_slice` for a sequence `BS`.
26   26  
27   A single buffer is closed under sub-ranging, so slicing it yields a 27   A single buffer is closed under sub-ranging, so slicing it yields a
28   buffer of the same kind. Any other sequence yields the generic 28   buffer of the same kind. Any other sequence yields the generic
29   `detail::slice_of<BS>` borrowed view. In both cases the result is itself 29   `detail::slice_of<BS>` borrowed view. In both cases the result is itself
30   a buffer sequence — `slice_type<BS> ∈ { buffer, slice_of<BS> }`. 30   a buffer sequence — `slice_type<BS> ∈ { buffer, slice_of<BS> }`.
31   */ 31   */
32   template<class BS> 32   template<class BS>
33   using slice_type = std::conditional_t< 33   using slice_type = std::conditional_t<
34   std::convertible_to<BS, const_buffer>, 34   std::convertible_to<BS, const_buffer>,
35   buffer_type<BS>, 35   buffer_type<BS>,
36   detail::slice_of<BS>>; 36   detail::slice_of<BS>>;
37   37  
38   /** Return a byte sub-range of a buffer sequence, as a value. 38   /** Return a byte sub-range of a buffer sequence, as a value.
39   39  
40   The result is itself a buffer sequence (`slice_type<BS>`): pass it 40   The result is itself a buffer sequence (`slice_type<BS>`): pass it
41   directly to any operation expecting a buffer sequence — there is no 41   directly to any operation expecting a buffer sequence — there is no
42   `.data()` and no separate concept to bind. For a single buffer the 42   `.data()` and no separate concept to bind. For a single buffer the
43   result is an adjusted buffer; for any other sequence it is a borrowed 43   result is an adjusted buffer; for any other sequence it is a borrowed
44   `slice_of<BS>` view. 44   `slice_of<BS>` view.
45   45  
46   @par Lifetime 46   @par Lifetime
47   Except for the single-buffer case, the result borrows `seq`: it stores 47   Except for the single-buffer case, the result borrows `seq`: it stores
48   iterators into the sequence, not a copy. `seq` must outlive the result. 48   iterators into the sequence, not a copy. `seq` must outlive the result.
49   The rvalue overload is deleted so a temporary cannot be sliced into a 49   The rvalue overload is deleted so a temporary cannot be sliced into a
50   dangling view. 50   dangling view.
51   51  
52   @par Complexity 52   @par Complexity
53   Single forward pass to the cut points; never sums the whole sequence. 53   Single forward pass to the cut points; never sums the whole sequence.
54   54  
55   @param seq The sequence to slice. Must outlive the result. 55   @param seq The sequence to slice. Must outlive the result.
56   @param offset Bytes skipped from the front. Clamped to the total size. 56   @param offset Bytes skipped from the front. Clamped to the total size.
57   @param length Bytes exposed, starting at `offset`. Defaults to the end. 57   @param length Bytes exposed, starting at `offset`. Defaults to the end.
58   58  
59   @return A `slice_type<BS>` value modeling the same buffer-sequence 59   @return A `slice_type<BS>` value modeling the same buffer-sequence
60   concept as `seq` (mutable if `seq` is mutable). 60   concept as `seq` (mutable if `seq` is mutable).
61   61  
62   @par Example 62   @par Example
63   @code 63   @code
64   co_await write(sock, buffer_slice(bufs, 0, 16384)); // first 16 KB 64   co_await write(sock, buffer_slice(bufs, 0, 16384)); // first 16 KB
65   auto rest = buffer_slice(bufs, n); // drop first n 65   auto rest = buffer_slice(bufs, n); // drop first n
66   @endcode 66   @endcode
67   67  
68   @see slice_type, consuming_buffers 68   @see slice_type, consuming_buffers
69   */ 69   */
70   template<class BufferSequence> 70   template<class BufferSequence>
71   requires MutableBufferSequence<BufferSequence> 71   requires MutableBufferSequence<BufferSequence>
72   || ConstBufferSequence<BufferSequence> 72   || ConstBufferSequence<BufferSequence>
73   slice_type<BufferSequence> 73   slice_type<BufferSequence>
HITCBC 74   2576 buffer_slice( 74   2576 buffer_slice(
75   BufferSequence const& seq, 75   BufferSequence const& seq,
76   std::size_t offset = 0, 76   std::size_t offset = 0,
77   std::size_t length = 77   std::size_t length =
78   (std::numeric_limits<std::size_t>::max)()) noexcept 78   (std::numeric_limits<std::size_t>::max)()) noexcept
79   { 79   {
80   if constexpr (std::convertible_to<BufferSequence, const_buffer>) 80   if constexpr (std::convertible_to<BufferSequence, const_buffer>)
81   { 81   {
82   // A single buffer is its own slice: advance and (maybe) truncate. 82   // A single buffer is its own slice: advance and (maybe) truncate.
HITCBC 83   292 buffer_type<BufferSequence> b = seq; 83   292 buffer_type<BufferSequence> b = seq;
HITCBC 84   292 b += offset; // operator+= clamps to size() 84   292 b += offset; // operator+= clamps to size()
HITCBC 85   292 if (length < b.size()) 85   292 if (length < b.size())
HITCBC 86   115 b = buffer_type<BufferSequence>(b.data(), length); 86   115 b = buffer_type<BufferSequence>(b.data(), length);
HITCBC 87   292 return b; 87   292 return b;
88   } 88   }
89   else 89   else
90   { 90   {
HITCBC 91   2284 return detail::slice_of<BufferSequence>(seq, offset, length); 91   2284 return detail::slice_of<BufferSequence>(seq, offset, length);
92   } 92   }
93   } 93   }
94   94  
95   /** Deleted rvalue overload. 95   /** Deleted rvalue overload.
96   96  
97   Slicing a temporary would yield an immediately dangling view (the 97   Slicing a temporary would yield an immediately dangling view (the
98   result borrows the sequence). Hoist the sequence into a named variable 98   result borrows the sequence). Hoist the sequence into a named variable
99   first. 99   first.
100   */ 100   */
101   template<class BufferSequence> 101   template<class BufferSequence>
102   requires MutableBufferSequence<BufferSequence> 102   requires MutableBufferSequence<BufferSequence>
103   || ConstBufferSequence<BufferSequence> 103   || ConstBufferSequence<BufferSequence>
104   slice_type<BufferSequence> 104   slice_type<BufferSequence>
105   buffer_slice( 105   buffer_slice(
106   BufferSequence const&& seq, 106   BufferSequence const&& seq,
107   std::size_t offset = 0, 107   std::size_t offset = 0,
108   std::size_t length = 108   std::size_t length =
109   (std::numeric_limits<std::size_t>::max)()) = delete; 109   (std::numeric_limits<std::size_t>::max)()) = delete;
110   110  
111   } // namespace capy 111   } // namespace capy
112   } // namespace boost 112   } // namespace boost
113   113  
114   #endif 114   #endif