File indexing completed on 2024-12-15 04:01:20

0001 /*
0002  * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best>
0003  *
0004  * SPDX-License-Identifier: GPL-3.0-or-later
0005  */
0006 #pragma once
0007 
0008 #include <iterator>
0009 
0010 namespace glaxnimate::utils {
0011 
0012 /**
0013  * \brief CRTP that adds all the boilerplate of an iterator
0014  * wrapping a random-access iterator.
0015  *
0016  * All you need to do is overload operator->() and operator*().
0017  */
0018 template<class Iterator, class BaseIterator>
0019 class RandomAccessIteratorWrapper
0020 {
0021 public:
0022     using iterator_category = std::random_access_iterator_tag;
0023     using difference_type = typename BaseIterator::difference_type;
0024 
0025     // Iterator
0026     RandomAccessIteratorWrapper& operator++() { ++iter; return *this; }
0027 
0028     // Input/Output Iterator
0029     bool operator==(const RandomAccessIteratorWrapper& o) const { return iter == o.iter; }
0030     bool operator!=(const RandomAccessIteratorWrapper& o) const { return iter != o.iter; }
0031     Iterator operator++(int) { auto copy = *this; ++iter; return copy; }
0032 
0033     // Forward Iterator
0034     RandomAccessIteratorWrapper() = default;
0035 
0036     // Bidirectional Iterator
0037     Iterator& operator--() { --iter; return *cast_derived(); }
0038     Iterator operator--(int) { auto copy = *this; --iter; return copy; }
0039 
0040     // Random Access Iterator
0041     Iterator& operator+= (difference_type i) { iter += i; return *cast_derived(); }
0042     Iterator operator+ (difference_type i) const { return iter + i; }
0043     friend Iterator operator+ (difference_type i, const Iterator& iter) { return iter.iter + i; }
0044     Iterator& operator-= (difference_type i) { iter -= i; return *cast_derived(); }
0045     Iterator operator- (difference_type i) const { return iter - i; }
0046     Iterator operator- (const Iterator& o) const { return iter - o.iter; }
0047     bool operator<(const Iterator& o) const { return iter < o.iter; }
0048     bool operator<=(const Iterator& o) const { return iter <= o.iter; }
0049     bool operator>(const Iterator& o) const { return iter > o.iter; }
0050     bool operator>=(const Iterator& o) const { return iter >= o.iter; }
0051 
0052 protected:
0053     using InternalIterator = BaseIterator;
0054     using Parent = RandomAccessIteratorWrapper;
0055     RandomAccessIteratorWrapper(BaseIterator iter) : iter(std::move(iter)) {}
0056     BaseIterator iter;
0057 
0058 private:
0059     Iterator* cast_derived() { return static_cast<Iterator*>(this); }
0060     const Iterator* cast_derived() const { return static_cast<const Iterator*>(this); }
0061 };
0062 } // namespace glaxnimate::utils