LCOV - code coverage report
Current view: top level - src/include/panoc-alm/util - ringbuffer.hpp (source / functions) Hit Total Coverage
Test: ecee3ec3a495b05c61f077aa7a236b7e00601437 Lines: 52 52 100.0 %
Date: 2021-11-04 22:49:09 Functions: 45 45 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include <cstddef>
       4             : #include <iterator>
       5             : 
       6             : namespace pa {
       7             : 
       8             : template <class IndexT = size_t>
       9             : struct CircularIndices {
      10             :     using Index = IndexT;
      11          83 :     CircularIndices(Index zerobased, Index circular)
      12          83 :         : zerobased(zerobased), circular(circular) {}
      13             :     Index zerobased;
      14             :     Index circular;
      15             : };
      16             : /// @related    CircularIndices
      17             : /// @note   Only valid for two indices in the same range.
      18             : template <class IndexT>
      19         235 : bool operator==(CircularIndices<IndexT> a, CircularIndices<IndexT> b) {
      20         235 :     return a.zerobased == b.zerobased;
      21             : }
      22             : /// @related    CircularIndices
      23             : /// @note   Only valid for two indices in the same range.
      24             : template <class IndexT>
      25             : bool operator!=(CircularIndices<IndexT> a, CircularIndices<IndexT> b) {
      26             :     return !(a == b);
      27             : }
      28             : 
      29             : template <class IndexT = size_t>
      30             : struct CircularIndexIterator {
      31             :     using Index   = IndexT;
      32             :     using Indices = CircularIndices<Index>;
      33             : 
      34             :     CircularIndexIterator() : i{0, 0}, max{0} {}
      35         166 :     CircularIndexIterator(Indices i, Index max) : i(i), max(max) {}
      36             : 
      37             :     Indices i;
      38             :     Index max;
      39             : 
      40             :     using value_type        = Indices;
      41             :     using reference         = value_type;
      42             :     using difference_type   = std::ptrdiff_t; // This is required but not used
      43             :     using pointer           = void;
      44             :     using iterator_category = std::input_iterator_tag;
      45             : 
      46         338 :     reference operator*() const { return i; }
      47          95 :     CircularIndexIterator &operator++() {
      48          95 :         assert(i.zerobased < max);
      49          95 :         ++i.zerobased;
      50          95 :         i.circular = i.circular + 1 == max ? Index{0} : i.circular + 1;
      51          95 :         return *this;
      52             :     }
      53         152 :     CircularIndexIterator &operator--() {
      54         152 :         assert(i.zerobased > 0);
      55         152 :         --i.zerobased;
      56         152 :         i.circular = i.circular == Index{0} ? max - 1 : i.circular - 1;
      57         152 :         return *this;
      58             :     }
      59           1 :     CircularIndexIterator operator++(int) {
      60           1 :         auto r = *this;
      61           1 :         ++(*this);
      62           1 :         return r;
      63             :     }
      64             :     CircularIndexIterator operator--(int) {
      65             :         auto r = *this;
      66             :         --(*this);
      67             :         return r;
      68             :     }
      69             : };
      70             : 
      71             : /// @related    CircularIndexIterator
      72             : /// @note   Only valid for two indices in the same range.
      73             : template <class IndexT>
      74         234 : bool operator==(CircularIndexIterator<IndexT> a,
      75             :                 CircularIndexIterator<IndexT> b) {
      76         234 :     assert(a.max == b.max);
      77         234 :     return a.i == b.i;
      78             : }
      79             : /// @related    CircularIndexIterator
      80             : /// @note   Only valid for two indices in the same range.
      81             : template <class IndexT>
      82         135 : bool operator!=(CircularIndexIterator<IndexT> a,
      83             :                 CircularIndexIterator<IndexT> b) {
      84         135 :     return !(a == b);
      85             : }
      86             : 
      87             : template <class IndexT = size_t>
      88             : struct ReverseCircularIndexIterator {
      89             :     using ForwardIterator = CircularIndexIterator<IndexT>;
      90             :     using Index           = typename ForwardIterator::Index;
      91             :     using Indices         = typename ForwardIterator::Indices;
      92             : 
      93             :     ReverseCircularIndexIterator() : forwardit() {}
      94             :     ReverseCircularIndexIterator(Indices i, Index max) : forwardit(i, max) {}
      95          40 :     ReverseCircularIndexIterator(ForwardIterator forwardit)
      96          40 :         : forwardit(forwardit) {}
      97             : 
      98             :     ForwardIterator forwardit;
      99             : 
     100             :     using value_type        = Indices;
     101             :     using reference         = value_type;
     102             :     using difference_type   = std::ptrdiff_t; // This is required but not used
     103             :     using pointer           = void;
     104             :     using iterator_category = std::input_iterator_tag;
     105             : 
     106          76 :     reference operator*() const {
     107          76 :         auto tmp = forwardit;
     108          76 :         return *(--tmp);
     109          76 :     }
     110          76 :     ReverseCircularIndexIterator &operator++() {
     111          76 :         --forwardit;
     112          76 :         return *this;
     113             :     }
     114             :     ReverseCircularIndexIterator &operator--() {
     115             :         ++forwardit;
     116             :         return *this;
     117             :     }
     118             :     ReverseCircularIndexIterator operator++(int) {
     119             :         auto r = *this;
     120             :         ++(*this);
     121             :         return r;
     122             :     }
     123             :     ReverseCircularIndexIterator operator--(int) {
     124             :         auto r = *this;
     125             :         --(*this);
     126             :         return r;
     127             :     }
     128             : };
     129             : 
     130             : /// @related    ReverseCircularIndexIterator
     131             : /// @note   Only valid for two indices in the same range.
     132             : template <class IndexT>
     133          96 : bool operator==(ReverseCircularIndexIterator<IndexT> a,
     134             :                 ReverseCircularIndexIterator<IndexT> b) {
     135          96 :     return a.forwardit == b.forwardit;
     136             : }
     137             : /// @related    ReverseCircularIndexIterator
     138             : /// @note   Only valid for two indices in the same range.
     139             : template <class IndexT>
     140          96 : bool operator!=(ReverseCircularIndexIterator<IndexT> a,
     141             :                 ReverseCircularIndexIterator<IndexT> b) {
     142          96 :     return !(a == b);
     143             : }
     144             : 
     145             : template <class IndexT>
     146             : class CircularRange {
     147             :   public:
     148             :     using Index   = IndexT;
     149             :     using Indices = CircularIndices<Index>;
     150             : 
     151          46 :     CircularRange(Index size, Index idx1, Index idx2, Index max)
     152          46 :         : size(size), idx1(idx1), idx2(idx2), max(max) {}
     153             : 
     154             :     using const_iterator = CircularIndexIterator<Index>;
     155             :     using iterator       = const_iterator;
     156             : 
     157             :     using const_reverse_iterator = ReverseCircularIndexIterator<Index>;
     158             :     using reverse_iterator       = const_reverse_iterator;
     159             : 
     160          76 :     iterator begin() const { return {{Index{0}, idx1}, max}; }
     161          90 :     iterator end() const { return {{size, idx2}, max}; }
     162             :     const_iterator cbegin() const { return begin(); }
     163             :     const_iterator cend() const { return end(); }
     164             : 
     165          40 :     reverse_iterator rbegin() const { return reverse_iterator{end()}; }
     166          40 :     reverse_iterator rend() const { return reverse_iterator{begin()}; }
     167             :     const_reverse_iterator crbegin() const {
     168             :         return const_reverse_iterator{end()};
     169             :     }
     170             :     const_reverse_iterator crend() const {
     171             :         return const_reverse_iterator{begin()};
     172             :     }
     173             : 
     174             :   private:
     175             :     Index size;
     176             :     Index idx1, idx2;
     177             :     Index max;
     178             : };
     179             : 
     180             : template <class IndexT>
     181             : class ReverseCircularRange {
     182             :   public:
     183             :     using ForwardRange = CircularRange<IndexT>;
     184             :     using Index        = typename ForwardRange::Index;
     185             :     using Indices      = typename ForwardRange::Indices;
     186             : 
     187          16 :     ReverseCircularRange(const ForwardRange &forwardrange)
     188          16 :         : forwardrange(forwardrange) {}
     189           6 :     ReverseCircularRange(Index size, Index idx1, Index idx2, Index max)
     190           6 :         : forwardrange(size, idx1, idx2, max) {}
     191             : 
     192             :     using const_iterator = typename ForwardRange::const_reverse_iterator;
     193             :     using iterator       = typename ForwardRange::reverse_iterator;
     194             : 
     195             :     using const_reverse_iterator = typename ForwardRange::const_iterator;
     196             :     using reverse_iterator       = typename ForwardRange::iterator;
     197             : 
     198          28 :     iterator begin() const { return forwardrange.rbegin(); }
     199          28 :     iterator end() const { return forwardrange.rend(); }
     200             :     const_iterator cbegin() const { return forwardrange.crbegin(); }
     201             :     const_iterator cend() const { return forwardrange.crend(); }
     202             : 
     203          12 :     reverse_iterator rbegin() const { return forwardrange.begin(); }
     204          12 :     reverse_iterator rend() const { return forwardrange.end(); }
     205             :     const_reverse_iterator crbegin() const { return forwardrange.cbegin(); }
     206             :     const_reverse_iterator crend() const { return forwardrange.cend(); }
     207             : 
     208             :   private:
     209             :     ForwardRange forwardrange;
     210             : };
     211             : 
     212             : } // namespace pa

Generated by: LCOV version 1.15