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   @par Parameters 51   @par Parameters
52   @li `seq` The underlying buffer sequence. Must outlive the 52   @li `seq` The underlying buffer sequence. Must outlive the
53   returned slice and any `data()` view obtained from it. 53   returned slice and any `data()` view obtained from it.
54   @li `offset` Number of bytes to skip from the start of `seq`. 54   @li `offset` Number of bytes to skip from the start of `seq`.
55   Clamped to `buffer_size(seq)`. 55   Clamped to `buffer_size(seq)`.
56   @li `length` Maximum number of bytes the slice will expose, 56   @li `length` Maximum number of bytes the slice will expose,
57   starting at `offset`. Clamped to `buffer_size(seq) - offset`. 57   starting at `offset`. Clamped to `buffer_size(seq) - offset`.
58   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".
59   59  
60   @par Example 60   @par Example
61   @code 61   @code
62   template< ReadStream Stream, MutableBufferSequence MB > 62   template< ReadStream Stream, MutableBufferSequence MB >
63   task< io_result< std::size_t > > 63   task< io_result< std::size_t > >
64   read_all( Stream& stream, MB buffers ) 64   read_all( Stream& stream, MB buffers )
65   { 65   {
66   auto s = buffer_slice( buffers ); 66   auto s = buffer_slice( buffers );
67   std::size_t const total_size = buffer_size( buffers ); 67   std::size_t const total_size = buffer_size( buffers );
68   std::size_t total = 0; 68   std::size_t total = 0;
69   while( total < total_size ) 69   while( total < total_size )
70   { 70   {
71   auto [ec, n] = co_await stream.read_some( s.data() ); 71   auto [ec, n] = co_await stream.read_some( s.data() );
72   s.remove_prefix( n ); 72   s.remove_prefix( n );
73   total += n; 73   total += n;
74   if( ec ) 74   if( ec )
75   co_return {ec, total}; 75   co_return {ec, total};
76   } 76   }
77   co_return {{}, total}; 77   co_return {{}, total};
78   } 78   }
79   @endcode 79   @endcode
80   80  
81   @see Slice, MutableSlice 81   @see Slice, MutableSlice
82   */ 82   */
83   template<class BufferSequence> 83   template<class BufferSequence>
84   requires MutableBufferSequence<BufferSequence> 84   requires MutableBufferSequence<BufferSequence>
85   || ConstBufferSequence<BufferSequence> 85   || ConstBufferSequence<BufferSequence>
86   auto 86   auto
HITCBC 87   4369 buffer_slice( 87   4369 buffer_slice(
88   BufferSequence const& seq, 88   BufferSequence const& seq,
89   std::size_t offset = 0, 89   std::size_t offset = 0,
90   std::size_t length = 90   std::size_t length =
91   (std::numeric_limits<std::size_t>::max)()) noexcept 91   (std::numeric_limits<std::size_t>::max)()) noexcept
92   { 92   {
HITCBC 93   4369 return detail::slice_impl<BufferSequence>(seq, offset, length); 93   4369 return detail::slice_impl<BufferSequence>(seq, offset, length);
94   } 94   }
95   95  
96   /** Deleted overload that rejects rvalue arguments at compile time. 96   /** Deleted overload that rejects rvalue arguments at compile time.
97   97  
98   Because the returned slice's validity depends on the underlying 98   Because the returned slice's validity depends on the underlying
99   buffer sequence remaining alive, calling `buffer_slice` with a 99   buffer sequence remaining alive, calling `buffer_slice` with a
100   temporary buffer sequence would produce an immediately dangling 100   temporary buffer sequence would produce an immediately dangling
101   slice. This overload makes such calls ill-formed, surfacing the 101   slice. This overload makes such calls ill-formed, surfacing the
102   lifetime error at compile time rather than as runtime UB. 102   lifetime error at compile time rather than as runtime UB.
103   103  
104   To slice a buffer sequence produced as a temporary, hoist it 104   To slice a buffer sequence produced as a temporary, hoist it
105   into a named variable first: 105   into a named variable first:
106   106  
107   @code 107   @code
108   auto bufs = some_dynamic_buffer.data(); // named, lives in scope 108   auto bufs = some_dynamic_buffer.data(); // named, lives in scope
109   auto s = buffer_slice( bufs ); // OK 109   auto s = buffer_slice( bufs ); // OK
110   @endcode 110   @endcode
111   */ 111   */
112   template<class BufferSequence> 112   template<class BufferSequence>
113   requires MutableBufferSequence<BufferSequence> 113   requires MutableBufferSequence<BufferSequence>
114   || ConstBufferSequence<BufferSequence> 114   || ConstBufferSequence<BufferSequence>
115   auto 115   auto
116   buffer_slice( 116   buffer_slice(
117   BufferSequence const&& seq, 117   BufferSequence const&& seq,
118   std::size_t offset = 0, 118   std::size_t offset = 0,
119   std::size_t length = 119   std::size_t length =
120   (std::numeric_limits<std::size_t>::max)()) = delete; 120   (std::numeric_limits<std::size_t>::max)()) = delete;
121   121  
122   } // namespace capy 122   } // namespace capy
123   } // namespace boost 123   } // namespace boost
124   124  
125   #endif 125   #endif