100.00% Lines (2/2) 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_impl.hpp> 15   #include <boost/capy/detail/slice_impl.hpp>
16   16  
17   #include <cstddef> 17   #include <cstddef>
18   #include <limits> 18   #include <limits>
19   19  
20   namespace boost { 20   namespace boost {
21   namespace capy { 21   namespace capy {
22   22  
23   /** Return a byte-range slice of a buffer sequence. 23   /** Return a byte-range slice of a buffer sequence.
24   24  
25   Constructs a view over a contiguous byte range of `seq`. The 25   Constructs a view over a contiguous byte range of `seq`. The
26   slice exposes its current bytes via `data()` (a buffer sequence) 26   slice exposes its current bytes via `data()` (a buffer sequence)
27   and supports incremental consumption via `remove_prefix(n)`. 27   and supports incremental consumption via `remove_prefix(n)`.
28   28  
29   @par Return Value 29   @par Return Value
30   An object of unspecified type satisfying the @ref Slice concept. 30   An object of unspecified type satisfying the @ref Slice concept.
31   Bind with `auto` and operate through the concept's members. When 31   Bind with `auto` and operate through the concept's members. When
32   `seq` models @ref MutableBufferSequence, the returned object 32   `seq` models @ref MutableBufferSequence, the returned object
33   additionally models @ref MutableSlice. 33   additionally models @ref MutableSlice.
34   34  
35   @par Lifetime 35   @par Lifetime
36   The returned slice is associated with `seq` as its underlying 36   The returned slice is associated with `seq` as its underlying
37   buffer sequence. `seq` — and the memory referenced by its buffer 37   buffer sequence. `seq` — and the memory referenced by its buffer
38   descriptors — must remain valid for as long as the slice, or 38   descriptors — must remain valid for as long as the slice, or
39   any buffer sequence obtained from its `data()`, is in use. 39   any buffer sequence obtained from its `data()`, is in use.
40   Passing a temporary buffer sequence to `buffer_slice` produces 40   Passing a temporary buffer sequence to `buffer_slice` produces
41   a dangling slice. 41   a dangling slice.
42   42  
43   The buffer sequence returned by `data()` is independent of the 43   The buffer sequence returned by `data()` is independent of the
44   slice object: subsequent operations on the slice (mutation, 44   slice object: subsequent operations on the slice (mutation,
45   copy, move, destruction) do not invalidate an already-obtained 45   copy, move, destruction) do not invalidate an already-obtained
46   `data()` view. It remains valid for as long as `seq` is valid. 46   `data()` view. It remains valid for as long as `seq` is valid.
47   47  
48   Iterators and buffer descriptors obtained through `data()` 48   Iterators and buffer descriptors obtained through `data()`
49   follow the same invalidation rules as those of `seq`. 49   follow the same invalidation rules as those of `seq`.
50   50  
51 - @param seq The underlying buffer sequence. Must outlive the 51 + @par Parameters
  52 + @li `seq` The underlying buffer sequence. Must outlive the
52   returned slice and any `data()` view obtained from it. 53   returned slice and any `data()` view obtained from it.
53 - 54 + @li `offset` Number of bytes to skip from the start of `seq`.
54 - @param offset Number of bytes to skip from the start of `seq`.  
55   Clamped to `buffer_size(seq)`. 55   Clamped to `buffer_size(seq)`.
56 - 56 + @li `length` Maximum number of bytes the slice will expose,
57 - @param length Maximum number of bytes the slice will expose,  
58   starting at `offset`. Clamped to `buffer_size(seq) - offset`. 57   starting at `offset`. Clamped to `buffer_size(seq) - offset`.
59   Defaults to the maximum value of `std::size_t`, i.e. "to end". 58   Defaults to the maximum value of `std::size_t`, i.e. "to end".
60   59  
61   @par Example 60   @par Example
62   @code 61   @code
63   template< ReadStream Stream, MutableBufferSequence MB > 62   template< ReadStream Stream, MutableBufferSequence MB >
64   task< io_result< std::size_t > > 63   task< io_result< std::size_t > >
65   read_all( Stream& stream, MB buffers ) 64   read_all( Stream& stream, MB buffers )
66   { 65   {
67   auto s = buffer_slice( buffers ); 66   auto s = buffer_slice( buffers );
68   std::size_t const total_size = buffer_size( buffers ); 67   std::size_t const total_size = buffer_size( buffers );
69   std::size_t total = 0; 68   std::size_t total = 0;
70   while( total < total_size ) 69   while( total < total_size )
71   { 70   {
72   auto [ec, n] = co_await stream.read_some( s.data() ); 71   auto [ec, n] = co_await stream.read_some( s.data() );
73   s.remove_prefix( n ); 72   s.remove_prefix( n );
74   total += n; 73   total += n;
75   if( ec ) 74   if( ec )
76   co_return {ec, total}; 75   co_return {ec, total};
77   } 76   }
78   co_return {{}, total}; 77   co_return {{}, total};
79   } 78   }
80   @endcode 79   @endcode
81   80  
82   @see Slice, MutableSlice 81   @see Slice, MutableSlice
83   */ 82   */
84   template<class BufferSequence> 83   template<class BufferSequence>
85   requires MutableBufferSequence<BufferSequence> 84   requires MutableBufferSequence<BufferSequence>
86   || ConstBufferSequence<BufferSequence> 85   || ConstBufferSequence<BufferSequence>
87   auto 86   auto
HITCBC 88   4370 buffer_slice( 87   4370 buffer_slice(
89   BufferSequence const& seq, 88   BufferSequence const& seq,
90   std::size_t offset = 0, 89   std::size_t offset = 0,
91   std::size_t length = 90   std::size_t length =
92   (std::numeric_limits<std::size_t>::max)()) noexcept 91   (std::numeric_limits<std::size_t>::max)()) noexcept
93   { 92   {
HITCBC 94   4370 return detail::slice_impl<BufferSequence>(seq, offset, length); 93   4370 return detail::slice_impl<BufferSequence>(seq, offset, length);
95   } 94   }
96   95  
97   /** Deleted overload that rejects rvalue arguments at compile time. 96   /** Deleted overload that rejects rvalue arguments at compile time.
98   97  
99   Because the returned slice's validity depends on the underlying 98   Because the returned slice's validity depends on the underlying
100   buffer sequence remaining alive, calling `buffer_slice` with a 99   buffer sequence remaining alive, calling `buffer_slice` with a
101   temporary buffer sequence would produce an immediately dangling 100   temporary buffer sequence would produce an immediately dangling
102   slice. This overload makes such calls ill-formed, surfacing the 101   slice. This overload makes such calls ill-formed, surfacing the
103   lifetime error at compile time rather than as runtime UB. 102   lifetime error at compile time rather than as runtime UB.
104   103  
105   To slice a buffer sequence produced as a temporary, hoist it 104   To slice a buffer sequence produced as a temporary, hoist it
106   into a named variable first: 105   into a named variable first:
107   106  
108   @code 107   @code
109   auto bufs = some_dynamic_buffer.data(); // named, lives in scope 108   auto bufs = some_dynamic_buffer.data(); // named, lives in scope
110   auto s = buffer_slice( bufs ); // OK 109   auto s = buffer_slice( bufs ); // OK
111 -  
112 - @param seq An rvalue buffer sequence (`const&&`). Binding the  
113 - slice to a temporary would dangle, so this overload is  
114 - deleted to reject such calls at compile time.  
115 -  
116 - @param offset Number of bytes to skip from the start of `seq`.  
117 -  
118 - @param length Maximum number of bytes the slice would expose,  
119 - starting at `offset`.  
120   @endcode 110   @endcode
121   */ 111   */
122   template<class BufferSequence> 112   template<class BufferSequence>
123   requires MutableBufferSequence<BufferSequence> 113   requires MutableBufferSequence<BufferSequence>
124   || ConstBufferSequence<BufferSequence> 114   || ConstBufferSequence<BufferSequence>
125   auto 115   auto
126   buffer_slice( 116   buffer_slice(
127   BufferSequence const&& seq, 117   BufferSequence const&& seq,
128   std::size_t offset = 0, 118   std::size_t offset = 0,
129   std::size_t length = 119   std::size_t length =
130   (std::numeric_limits<std::size_t>::max)()) = delete; 120   (std::numeric_limits<std::size_t>::max)()) = delete;
131   121  
132   } // namespace capy 122   } // namespace capy
133   } // namespace boost 123   } // namespace boost
134   124  
135   #endif 125   #endif