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