| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
| file Copyright.txt or https://cmake.org/licensing for details. */ |
| #pragma once |
| |
| #include "cmConfigure.h" // IWYU pragma: keep |
| |
| #include <algorithm> |
| #include <functional> |
| #include <iterator> |
| |
| namespace RangeIterators { |
| |
| template <typename Iter, typename UnaryPredicate> |
| class FilterIterator |
| { |
| public: |
| using iterator_category = std::bidirectional_iterator_tag; |
| using value_type = typename std::iterator_traits<Iter>::value_type; |
| using difference_type = typename std::iterator_traits<Iter>::difference_type; |
| using pointer = typename std::iterator_traits<Iter>::pointer; |
| using reference = typename std::iterator_traits<Iter>::reference; |
| |
| FilterIterator(Iter b, Iter e, UnaryPredicate p) |
| : Cur(std::move(b)) |
| , End(std::move(e)) |
| , Pred(std::move(p)) |
| { |
| this->SatisfyPredicate(); |
| } |
| |
| FilterIterator& operator++() |
| { |
| ++this->Cur; |
| this->SatisfyPredicate(); |
| return *this; |
| } |
| |
| FilterIterator& operator--() |
| { |
| do { |
| --this->Cur; |
| } while (!this->Pred(*this->Cur)); |
| return *this; |
| } |
| |
| bool operator==(FilterIterator const& other) const |
| { |
| return this->Cur == other.Cur; |
| } |
| |
| bool operator!=(FilterIterator const& other) const |
| { |
| return !this->operator==(other); |
| } |
| |
| auto operator*() const -> decltype(*std::declval<Iter>()) |
| { |
| return *this->Cur; |
| } |
| |
| private: |
| void SatisfyPredicate() |
| { |
| while (this->Cur != this->End && !this->Pred(*this->Cur)) { |
| ++this->Cur; |
| } |
| } |
| |
| Iter Cur; |
| Iter End; |
| UnaryPredicate Pred; |
| }; |
| |
| template <typename Iter, typename UnaryFunction> |
| class TransformIterator |
| { |
| public: |
| using iterator_category = std::bidirectional_iterator_tag; |
| using value_type = typename std::remove_cv< |
| typename std::remove_reference<decltype(std::declval<UnaryFunction>()( |
| *std::declval<Iter>()))>::type>::type; |
| using difference_type = typename std::iterator_traits<Iter>::difference_type; |
| using pointer = value_type const*; |
| using reference = value_type const&; |
| |
| TransformIterator(Iter i, UnaryFunction f) |
| : Base(std::move(i)) |
| , Func(std::move(f)) |
| { |
| } |
| |
| TransformIterator& operator++() |
| { |
| ++this->Base; |
| return *this; |
| } |
| |
| TransformIterator& operator--() |
| { |
| --this->Base; |
| return *this; |
| } |
| |
| bool operator==(TransformIterator const& other) const |
| { |
| return this->Base == other.Base; |
| } |
| |
| bool operator!=(TransformIterator const& other) const |
| { |
| return !this->operator==(other); |
| } |
| |
| auto operator*() const |
| -> decltype(std::declval<UnaryFunction>()(*std::declval<Iter>())) |
| { |
| return this->Func(*this->Base); |
| } |
| |
| private: |
| Iter Base; |
| UnaryFunction Func; |
| }; |
| |
| } // namespace RangeIterators |
| |
| template <typename Iter> |
| class cmRange |
| { |
| public: |
| using const_iterator = Iter; |
| using value_type = typename std::iterator_traits<Iter>::value_type; |
| using difference_type = typename std::iterator_traits<Iter>::difference_type; |
| |
| cmRange(Iter b, Iter e) |
| : Begin(std::move(b)) |
| , End(std::move(e)) |
| { |
| } |
| |
| Iter begin() const { return this->Begin; } |
| Iter end() const { return this->End; } |
| bool empty() const { return this->Begin == this->End; } |
| |
| difference_type size() const |
| { |
| return std::distance(this->Begin, this->End); |
| } |
| |
| cmRange& advance(difference_type amount) & |
| { |
| std::advance(this->Begin, amount); |
| return *this; |
| } |
| |
| cmRange advance(difference_type amount) && |
| { |
| std::advance(this->Begin, amount); |
| return std::move(*this); |
| } |
| |
| cmRange& retreat(difference_type amount) & |
| { |
| std::advance(this->End, -amount); |
| return *this; |
| } |
| |
| cmRange retreat(difference_type amount) && |
| { |
| std::advance(this->End, -amount); |
| return std::move(*this); |
| } |
| |
| template <typename UnaryPredicate> |
| bool all_of(UnaryPredicate p) const |
| { |
| return std::all_of(this->Begin, this->End, std::ref(p)); |
| } |
| |
| template <typename UnaryPredicate> |
| bool any_of(UnaryPredicate p) const |
| { |
| return std::any_of(this->Begin, this->End, std::ref(p)); |
| } |
| |
| template <typename UnaryPredicate> |
| bool none_of(UnaryPredicate p) const |
| { |
| return std::none_of(this->Begin, this->End, std::ref(p)); |
| } |
| |
| template <typename UnaryPredicate> |
| auto filter(UnaryPredicate p) const |
| -> cmRange<RangeIterators::FilterIterator<Iter, UnaryPredicate>> |
| { |
| using It = RangeIterators::FilterIterator<Iter, UnaryPredicate>; |
| return { It(this->Begin, this->End, p), It(this->End, this->End, p) }; |
| } |
| |
| template <typename UnaryFunction> |
| auto transform(UnaryFunction f) const |
| -> cmRange<RangeIterators::TransformIterator<Iter, UnaryFunction>> |
| { |
| using It = RangeIterators::TransformIterator<Iter, UnaryFunction>; |
| return { It(this->Begin, f), It(this->End, f) }; |
| } |
| |
| private: |
| Iter Begin; |
| Iter End; |
| }; |
| |
| template <typename Iter1, typename Iter2> |
| bool operator==(cmRange<Iter1> const& left, cmRange<Iter2> const& right) |
| { |
| return left.size() == right.size() && |
| std::equal(left.begin(), left.end(), right.begin()); |
| } |
| |
| template <typename Iter1, typename Iter2> |
| auto cmMakeRange(Iter1 begin, Iter2 end) -> cmRange<Iter1> |
| { |
| return { begin, end }; |
| } |
| |
| template <typename Range> |
| auto cmMakeRange(Range const& range) -> cmRange<decltype(range.begin())> |
| { |
| return { range.begin(), range.end() }; |
| } |
| |
| template <typename Range> |
| auto cmReverseRange(Range const& range) -> cmRange<decltype(range.rbegin())> |
| { |
| return { range.rbegin(), range.rend() }; |
| } |