100.00% Lines (7/7) 100.00% Functions (1/1)
TLA Baseline Branch
Line Hits Code Line Hits 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 + /** Names whichever buffer type `buffer_slice` returns 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>`), so 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 + @par !example example
  64 +
  65 +
  66 + @see @ref slice_type, @ref consuming_buffers
  67 + */
  68 + template<class BufferSequence>
  69 + requires MutableBufferSequence<BufferSequence>
  70 + || ConstBufferSequence<BufferSequence>
  71 + slice_type<BufferSequence>
HITGNC   72 + 2670 buffer_slice(
  73 + BufferSequence const& seq,
  74 + std::size_t offset = 0,
  75 + std::size_t length =
  76 + (std::numeric_limits<std::size_t>::max)()) noexcept
  77 + {
  78 + if constexpr (std::convertible_to<BufferSequence, const_buffer>)
  79 + {
  80 + // A single buffer is its own slice: advance and (maybe) truncate.
HITGNC   81 + 384 buffer_type<BufferSequence> b = seq;
HITGNC   82 + 384 b += offset; // operator+= clamps to size()
HITGNC   83 + 384 if (length < b.size())
HITGNC   84 + 156 b = buffer_type<BufferSequence>(b.data(), length);
HITGNC   85 + 384 return b;
  86 + }
  87 + else
  88 + {
HITGNC   89 + 2286 return detail::slice_of<BufferSequence>(seq, offset, length);
  90 + }
  91 + }
  92 +
  93 + /** Rejects a temporary sequence at compile time, since the result would dangle.
  94 +
  95 + Slicing a temporary would yield an immediately dangling view (the
  96 + result borrows the sequence). Hoist the sequence into a named variable
  97 + first.
  98 + */
  99 + template<class BufferSequence>
  100 + requires MutableBufferSequence<BufferSequence>
  101 + || ConstBufferSequence<BufferSequence>
  102 + slice_type<BufferSequence>
  103 + buffer_slice(
  104 + BufferSequence const&& seq,
  105 + std::size_t offset = 0,
  106 + std::size_t length =
  107 + (std::numeric_limits<std::size_t>::max)()) = delete;
  108 +
  109 + } // namespace capy
  110 + } // namespace boost
  111 +
  112 + #endif