LCOV - code coverage report
Current view: top level - capy/detail - slice_impl.hpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 100.0 % 105 105
Test Date: 2026-05-13 16:13:25 Functions: 97.0 % 100 97 3

           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         493 :     static buffer_type adjust_buffer(
      67                 :         buffer_type const& buf,
      68                 :         std::size_t front,
      69                 :         std::size_t back) noexcept
      70                 :     {
      71                 :         if constexpr (std::is_same_v<buffer_type, mutable_buffer>)
      72                 :         {
      73             247 :             return mutable_buffer(
      74             247 :                 static_cast<char*>(buf.data()) + front,
      75             494 :                 buf.size() - front - back);
      76                 :         }
      77                 :         else
      78                 :         {
      79             246 :             return const_buffer(
      80             246 :                 static_cast<char const*>(buf.data()) + front,
      81             492 :                 buf.size() - front - back);
      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             942 :             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             942 :                 : cur_(cur)
     119             942 :                 , anchor_first_(anchor_first)
     120             942 :                 , anchor_last_(anchor_last)
     121             942 :                 , front_skip_(front_skip)
     122             942 :                 , back_skip_(back_skip)
     123                 :             {
     124             942 :             }
     125                 : 
     126             598 :             bool operator==(const_iterator const& other) const noexcept
     127                 :             {
     128             598 :                 return cur_ == other.cur_;
     129                 :             }
     130                 : 
     131             598 :             bool operator!=(const_iterator const& other) const noexcept
     132                 :             {
     133             598 :                 return !(*this == other);
     134                 :             }
     135                 : 
     136             493 :             value_type operator*() const noexcept
     137                 :             {
     138             493 :                 buffer_type buf = *cur_;
     139             493 :                 auto front = (cur_ == anchor_first_) ? front_skip_ : 0;
     140             493 :                 auto next = cur_;
     141             493 :                 ++next;
     142             493 :                 auto back = (next == anchor_last_) ? back_skip_ : 0;
     143             493 :                 return adjust_buffer(buf, front, back);
     144                 :             }
     145                 : 
     146             463 :             const_iterator& operator++() noexcept
     147                 :             {
     148             463 :                 ++cur_;
     149             463 :                 return *this;
     150                 :             }
     151                 : 
     152             262 :             const_iterator operator++(int) noexcept
     153                 :             {
     154             262 :                 const_iterator tmp = *this;
     155             262 :                 ++*this;
     156             262 :                 return tmp;
     157                 :             }
     158                 : 
     159                 :             const_iterator& operator--() noexcept
     160                 :             {
     161                 :                 --cur_;
     162                 :                 return *this;
     163                 :             }
     164                 : 
     165                 :             const_iterator operator--(int) noexcept
     166                 :             {
     167                 :                 const_iterator tmp = *this;
     168                 :                 --*this;
     169                 :                 return tmp;
     170                 :             }
     171                 :         };
     172                 : 
     173                 :         data_view() noexcept = default;
     174                 : 
     175             271 :         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             271 :             : first_(first)
     181             271 :             , last_(last)
     182             271 :             , front_skip_(front_skip)
     183             271 :             , back_skip_(back_skip)
     184                 :         {
     185             271 :         }
     186                 : 
     187             457 :         const_iterator begin() const noexcept
     188                 :         {
     189                 :             return const_iterator(
     190             457 :                 first_, first_, last_, front_skip_, back_skip_);
     191                 :         }
     192                 : 
     193             485 :         const_iterator end() const noexcept
     194                 :         {
     195                 :             return const_iterator(
     196             485 :                 last_, first_, last_, front_skip_, back_skip_);
     197                 :         }
     198                 :     };
     199                 : 
     200                 :     slice_impl() noexcept = default;
     201                 : 
     202              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             213 :     slice_impl(
     209                 :         BufferSequence const& bs,
     210                 :         std::size_t offset,
     211                 :         std::size_t length) noexcept
     212             213 :     {
     213             213 :         auto it_begin = capy::begin(bs);
     214             213 :         auto it_end = capy::end(bs);
     215                 : 
     216             213 :         std::size_t total = 0;
     217             508 :         for (auto it = it_begin; it != it_end; ++it)
     218             295 :             total += (*it).size();
     219                 : 
     220             213 :         if (offset > total)
     221               1 :             offset = total;
     222             213 :         std::size_t const remaining = total - offset;
     223             213 :         if (length > remaining)
     224             205 :             length = remaining;
     225                 : 
     226             213 :         first_ = it_begin;
     227             213 :         last_ = it_end;
     228                 : 
     229             213 :         std::size_t skip = offset;
     230             235 :         while (first_ != last_)
     231                 :         {
     232             228 :             std::size_t const buf_size = (*first_).size();
     233             228 :             if (skip < buf_size)
     234                 :             {
     235             206 :                 front_skip_ = skip;
     236             206 :                 break;
     237                 :             }
     238              22 :             skip -= buf_size;
     239              22 :             ++first_;
     240                 :         }
     241                 : 
     242             213 :         std::size_t left = length;
     243             213 :         auto cursor = first_;
     244             213 :         std::size_t cursor_front = front_skip_;
     245             278 :         while (cursor != last_ && left > 0)
     246                 :         {
     247             270 :             std::size_t const buf_size = (*cursor).size();
     248             270 :             std::size_t const avail = buf_size - cursor_front;
     249             270 :             if (left <= avail)
     250                 :             {
     251             205 :                 back_skip_ = avail - left;
     252             205 :                 ++cursor;
     253             205 :                 last_ = cursor;
     254             205 :                 return;
     255                 :             }
     256              65 :             left -= avail;
     257              65 :             ++cursor;
     258              65 :             cursor_front = 0;
     259                 :         }
     260                 : 
     261               8 :         last_ = cursor;
     262                 :     }
     263                 : 
     264             271 :     data_view data() const noexcept
     265                 :     {
     266             271 :         return data_view(first_, last_, front_skip_, back_skip_);
     267                 :     }
     268                 : 
     269             172 :     void remove_prefix(std::size_t n) noexcept
     270                 :     {
     271             192 :         while (n > 0 && first_ != last_)
     272                 :         {
     273             122 :             std::size_t const buf_total = (*first_).size();
     274             122 :             std::size_t live = buf_total - front_skip_;
     275             122 :             auto next = first_;
     276             122 :             ++next;
     277             122 :             bool const is_last = (next == last_);
     278             122 :             if (is_last)
     279              92 :                 live -= back_skip_;
     280                 : 
     281             122 :             if (n < live)
     282                 :             {
     283              35 :                 front_skip_ += n;
     284              35 :                 return;
     285                 :             }
     286                 : 
     287              87 :             n -= live;
     288              87 :             if (is_last)
     289                 :             {
     290              67 :                 first_ = last_;
     291              67 :                 front_skip_ = 0;
     292              67 :                 back_skip_ = 0;
     293              67 :                 return;
     294                 :             }
     295              20 :             ++first_;
     296              20 :             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