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