include/boost/capy/buffers/buffer_slice.hpp
100.0% Lines (7/7)
-% List of functions (0/1)
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 |