| /* 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() }; | |
| } |