LCOV - code coverage report
Current view: top level - capy/detail - slice_impl.hpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 99.1 % 113 112 1
Test Date: 2026-05-14 20:50:55 Functions: 96.0 % 175 168 7

           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                 : /*
      11                 :     Implementation type for the public buffer_slice() free function.
      12                 :     Users see this only via auto + the Slice concept; the type is
      13                 :     documented as unspecified. Maintained alongside Slice in
      14                 :     include/boost/capy/concept/slice.hpp.
      15                 : */
      16                 : 
      17                 : #ifndef BOOST_CAPY_DETAIL_SLICE_IMPL_HPP
      18                 : #define BOOST_CAPY_DETAIL_SLICE_IMPL_HPP
      19                 : 
      20                 : #include <boost/capy/detail/config.hpp>
      21                 : #include <boost/capy/buffers.hpp>
      22                 : 
      23                 : #include <cstddef>
      24                 : #include <iterator>
      25                 : #include <type_traits>
      26                 : 
      27                 : namespace boost {
      28                 : namespace capy {
      29                 : namespace detail {
      30                 : 
      31                 : template<class T>
      32                 : struct slice_buffer_type_for;
      33                 : 
      34                 : template<MutableBufferSequence T>
      35                 : struct slice_buffer_type_for<T>
      36                 : {
      37                 :     using type = mutable_buffer;
      38                 : };
      39                 : 
      40                 : template<ConstBufferSequence T>
      41                 :     requires (!MutableBufferSequence<T>)
      42                 : struct slice_buffer_type_for<T>
      43                 : {
      44                 :     using type = const_buffer;
      45                 : };
      46                 : 
      47                 : template<class BufferSequence>
      48                 :     requires MutableBufferSequence<BufferSequence>
      49                 :           || ConstBufferSequence<BufferSequence>
      50                 : class slice_impl
      51                 : {
      52                 : public:
      53                 :     using iterator_type =
      54                 :         decltype(capy::begin(std::declval<BufferSequence const&>()));
      55                 :     using end_iterator_type =
      56                 :         decltype(capy::end(std::declval<BufferSequence const&>()));
      57                 :     using buffer_type =
      58                 :         typename slice_buffer_type_for<BufferSequence>::type;
      59                 : 
      60                 : private:
      61                 :     iterator_type first_{};
      62                 :     end_iterator_type last_{};
      63                 :     std::size_t front_skip_ = 0;
      64                 :     std::size_t back_skip_ = 0;
      65                 : 
      66 HIT       42071 :     static buffer_type adjust_buffer(
      67                 :         buffer_type const& buf,
      68                 :         std::size_t front_n,
      69                 :         std::size_t back_n) noexcept
      70                 :     {
      71                 :         if constexpr (std::is_same_v<buffer_type, mutable_buffer>)
      72                 :         {
      73           18031 :             return mutable_buffer(
      74           18031 :                 static_cast<char*>(buf.data()) + front_n,
      75           36062 :                 buf.size() - front_n - back_n);
      76                 :         }
      77                 :         else
      78                 :         {
      79           24040 :             return const_buffer(
      80           24040 :                 static_cast<char const*>(buf.data()) + front_n,
      81           48080 :                 buf.size() - front_n - back_n);
      82                 :         }
      83                 :     }
      84                 : 
      85                 : public:
      86                 :     /// View returned by `slice_impl::data()`.
      87                 :     class data_view
      88                 :     {
      89                 :         iterator_type first_{};
      90                 :         end_iterator_type last_{};
      91                 :         std::size_t front_skip_ = 0;
      92                 :         std::size_t back_skip_ = 0;
      93                 : 
      94                 :     public:
      95                 :         class const_iterator
      96                 :         {
      97                 :             iterator_type cur_{};
      98                 :             iterator_type anchor_first_{};
      99                 :             end_iterator_type anchor_last_{};
     100                 :             std::size_t front_skip_ = 0;
     101                 :             std::size_t back_skip_ = 0;
     102                 : 
     103                 :         public:
     104                 :             using iterator_category = std::bidirectional_iterator_tag;
     105                 :             using value_type = buffer_type;
     106                 :             using difference_type = std::ptrdiff_t;
     107                 :             using pointer = value_type*;
     108                 :             using reference = value_type;
     109                 : 
     110                 :             const_iterator() noexcept = default;
     111                 : 
     112           69754 :             const_iterator(
     113                 :                 iterator_type cur,
     114                 :                 iterator_type anchor_first,
     115                 :                 end_iterator_type anchor_last,
     116                 :                 std::size_t front_skip,
     117                 :                 std::size_t back_skip) noexcept
     118           69754 :                 : cur_(cur)
     119           69754 :                 , anchor_first_(anchor_first)
     120           69754 :                 , anchor_last_(anchor_last)
     121           69754 :                 , front_skip_(front_skip)
     122           69754 :                 , back_skip_(back_skip)
     123                 :             {
     124           69754 :             }
     125                 : 
     126           76234 :             bool operator==(const_iterator const& other) const noexcept
     127                 :             {
     128           76234 :                 return cur_ == other.cur_;
     129                 :             }
     130                 : 
     131           76234 :             bool operator!=(const_iterator const& other) const noexcept
     132                 :             {
     133           76234 :                 return !(*this == other);
     134                 :             }
     135                 : 
     136           42071 :             value_type operator*() const noexcept
     137                 :             {
     138           42071 :                 buffer_type buf = *cur_;
     139           42071 :                 auto front_n = (cur_ == anchor_first_) ? front_skip_ : 0;
     140           42071 :                 auto next = cur_;
     141           42071 :                 ++next;
     142           42071 :                 auto back_n = (next == anchor_last_) ? back_skip_ : 0;
     143           42071 :                 return adjust_buffer(buf, front_n, back_n);
     144                 :             }
     145                 : 
     146           29897 :             const_iterator& operator++() noexcept
     147                 :             {
     148           29897 :                 ++cur_;
     149           29897 :                 return *this;
     150                 :             }
     151                 : 
     152            6512 :             const_iterator operator++(int) noexcept
     153                 :             {
     154            6512 :                 const_iterator tmp = *this;
     155            6512 :                 ++*this;
     156            6512 :                 return tmp;
     157                 :             }
     158                 : 
     159           12144 :             const_iterator& operator--() noexcept
     160                 :             {
     161           12144 :                 --cur_;
     162           12144 :                 return *this;
     163                 :             }
     164                 : 
     165            6072 :             const_iterator operator--(int) noexcept
     166                 :             {
     167            6072 :                 const_iterator tmp = *this;
     168            6072 :                 --*this;
     169            6072 :                 return tmp;
     170                 :             }
     171                 :         };
     172                 : 
     173                 :         data_view() noexcept = default;
     174                 : 
     175           10692 :         data_view(
     176                 :             iterator_type first,
     177                 :             end_iterator_type last,
     178                 :             std::size_t front_skip,
     179                 :             std::size_t back_skip) noexcept
     180           10692 :             : first_(first)
     181           10692 :             , last_(last)
     182           10692 :             , front_skip_(front_skip)
     183           10692 :             , back_skip_(back_skip)
     184                 :         {
     185           10692 :         }
     186                 : 
     187           34863 :         const_iterator begin() const noexcept
     188                 :         {
     189                 :             return const_iterator(
     190           34863 :                 first_, first_, last_, front_skip_, back_skip_);
     191                 :         }
     192                 : 
     193           34891 :         const_iterator end() const noexcept
     194                 :         {
     195                 :             return const_iterator(
     196           34891 :                 last_, first_, last_, front_skip_, back_skip_);
     197                 :         }
     198                 :     };
     199                 : 
     200 MIS           0 :     slice_impl() noexcept = default;
     201                 : 
     202 HIT          10 :     explicit slice_impl(BufferSequence const& bs) noexcept
     203              10 :         : first_(capy::begin(bs))
     204              10 :         , last_(capy::end(bs))
     205                 :     {
     206              10 :     }
     207                 : 
     208            4377 :     slice_impl(
     209                 :         BufferSequence const& bs,
     210                 :         std::size_t offset,
     211                 :         std::size_t length) noexcept
     212            4377 :     {
     213            4377 :         auto it_begin = capy::begin(bs);
     214            4377 :         auto it_end = capy::end(bs);
     215                 : 
     216            4377 :         std::size_t total = 0;
     217           10956 :         for (auto it = it_begin; it != it_end; ++it)
     218            6579 :             total += (*it).size();
     219                 : 
     220            4377 :         if (offset > total)
     221               1 :             offset = total;
     222            4377 :         std::size_t const remaining = total - offset;
     223            4377 :         if (length > remaining)
     224            2293 :             length = remaining;
     225                 : 
     226            4377 :         first_ = it_begin;
     227            4377 :         last_ = it_end;
     228                 : 
     229            4377 :         std::size_t skip = offset;
     230            4756 :         while (first_ != last_)
     231                 :         {
     232            4658 :             std::size_t const buf_size = (*first_).size();
     233            4658 :             if (skip < buf_size)
     234                 :             {
     235            4279 :                 front_skip_ = skip;
     236            4279 :                 break;
     237                 :             }
     238             379 :             skip -= buf_size;
     239             379 :             ++first_;
     240                 :         }
     241                 : 
     242            4377 :         std::size_t left = length;
     243            4377 :         auto cursor = first_;
     244            4377 :         std::size_t cursor_front = front_skip_;
     245            5734 :         while (cursor != last_ && left > 0)
     246                 :         {
     247            5358 :             std::size_t const buf_size = (*cursor).size();
     248            5358 :             std::size_t const avail = buf_size - cursor_front;
     249            5358 :             if (left <= avail)
     250                 :             {
     251            4001 :                 back_skip_ = avail - left;
     252            4001 :                 ++cursor;
     253            4001 :                 last_ = cursor;
     254            4001 :                 return;
     255                 :             }
     256            1357 :             left -= avail;
     257            1357 :             ++cursor;
     258            1357 :             cursor_front = 0;
     259                 :         }
     260                 : 
     261             376 :         last_ = cursor;
     262                 :     }
     263                 : 
     264           10692 :     data_view data() const noexcept
     265                 :     {
     266           10692 :         return data_view(first_, last_, front_skip_, back_skip_);
     267                 :     }
     268                 : 
     269             746 :     void remove_prefix(std::size_t n) noexcept
     270                 :     {
     271            1062 :         while (n > 0 && first_ != last_)
     272                 :         {
     273             922 :             std::size_t const buf_total = (*first_).size();
     274             922 :             std::size_t live = buf_total - front_skip_;
     275             922 :             auto next = first_;
     276             922 :             ++next;
     277             922 :             bool const is_last = (next == last_);
     278             922 :             if (is_last)
     279             406 :                 live -= back_skip_;
     280                 : 
     281             922 :             if (n < live)
     282                 :             {
     283             467 :                 front_skip_ += n;
     284             471 :                 return;
     285                 :             }
     286                 : 
     287             455 :             n -= live;
     288             455 :             if (is_last)
     289                 :             {
     290             139 :                 first_ = last_;
     291             139 :                 front_skip_ = 0;
     292             139 :                 back_skip_ = 0;
     293             139 :                 return;
     294                 :             }
     295             316 :             ++first_;
     296             316 :             front_skip_ = 0;
     297                 :         }
     298                 :     }
     299                 : };
     300                 : 
     301                 : } // namespace detail
     302                 : } // namespace capy
     303                 : } // namespace boost
     304                 : 
     305                 : #endif
        

Generated by: LCOV version 2.3