include/boost/capy/buffers/buffer_slice.hpp

100.0% Lines (7/7) -% List of functions (0/1)
buffer_slice.hpp
f(x) Functions (1)
Function Calls Lines Blocks
<unknown function 74> :74
Line TLA Hits 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_of.hpp>
16
17 #include <concepts>
18 #include <cstddef>
19 #include <limits>
20 #include <type_traits>
21
22 namespace boost {
23 namespace capy {
24
25 /** The type produced by `buffer_slice` for a sequence `BS`.
26
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
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> }`.
31 */
32 template<class BS>
33 using slice_type = std::conditional_t<
34 std::convertible_to<BS, const_buffer>,
35 buffer_type<BS>,
36 detail::slice_of<BS>>;
37
38 /** Return a byte sub-range of a buffer sequence, as a value.
39
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
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
44 `slice_of<BS>` view.
45
46 @par Lifetime
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.
49 The rvalue overload is deleted so a temporary cannot be sliced into a
50 dangling view.
51
52 @par Complexity
53 Single forward pass to the cut points; never sums the whole sequence.
54
55 @param seq The sequence to slice. Must outlive the result.
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.
58
59 @return A `slice_type<BS>` value modeling the same buffer-sequence
60 concept as `seq` (mutable if `seq` is mutable).
61
62 @par Example
63 @code
64 co_await write(sock, buffer_slice(bufs, 0, 16384)); // first 16 KB
65 auto rest = buffer_slice(bufs, n); // drop first n
66 @endcode
67
68 @see slice_type, consuming_buffers
69 */
70 template<class BufferSequence>
71 requires MutableBufferSequence<BufferSequence>
72 || ConstBufferSequence<BufferSequence>
73 slice_type<BufferSequence>
74 2576x buffer_slice(
75 BufferSequence const& seq,
76 std::size_t offset = 0,
77 std::size_t length =
78 (std::numeric_limits<std::size_t>::max)()) noexcept
79 {
80 if constexpr (std::convertible_to<BufferSequence, const_buffer>)
81 {
82 // A single buffer is its own slice: advance and (maybe) truncate.
83 292x buffer_type<BufferSequence> b = seq;
84 292x b += offset; // operator+= clamps to size()
85 292x if (length < b.size())
86 115x b = buffer_type<BufferSequence>(b.data(), length);
87 292x return b;
88 }
89 else
90 {
91 2284x return detail::slice_of<BufferSequence>(seq, offset, length);
92 }
93 }
94
95 /** Deleted rvalue overload.
96
97 Slicing a temporary would yield an immediately dangling view (the
98 result borrows the sequence). Hoist the sequence into a named variable
99 first.
100 */
101 template<class BufferSequence>
102 requires MutableBufferSequence<BufferSequence>
103 || ConstBufferSequence<BufferSequence>
104 slice_type<BufferSequence>
105 buffer_slice(
106 BufferSequence const&& seq,
107 std::size_t offset = 0,
108 std::size_t length =
109 (std::numeric_limits<std::size_t>::max)()) = delete;
110
111 } // namespace capy
112 } // namespace boost
113
114 #endif
115