| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350 |
- // Copyright (c) 2016 Google Inc.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- #ifndef SOURCE_OPT_ITERATOR_H_
- #define SOURCE_OPT_ITERATOR_H_
- #include <cstddef> // for ptrdiff_t
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <utility>
- #include <vector>
- namespace spvtools {
- namespace opt {
- // An ad hoc iterator class for std::vector<std::unique_ptr<|ValueType|>>. The
- // purpose of this iterator class is to provide transparent access to those
- // std::unique_ptr managed elements in the vector, behaving like we are using
- // std::vector<|ValueType|>.
- template <typename ValueType, bool IsConst = false>
- class UptrVectorIterator {
- public:
- using iterator_category = std::random_access_iterator_tag;
- using value_type = ValueType;
- using pointer = value_type*;
- using reference = value_type&;
- using difference_type = std::ptrdiff_t;
- // Type aliases. We need to apply constness properly if |IsConst| is true.
- using Uptr = std::unique_ptr<ValueType>;
- using UptrVector = typename std::conditional<IsConst, const std::vector<Uptr>,
- std::vector<Uptr>>::type;
- using UnderlyingIterator =
- typename std::conditional<IsConst, typename UptrVector::const_iterator,
- typename UptrVector::iterator>::type;
- // Creates a new iterator from the given |container| and its raw iterator
- // |it|.
- UptrVectorIterator(UptrVector* container, const UnderlyingIterator& it)
- : container_(container), iterator_(it) {}
- UptrVectorIterator(const UptrVectorIterator&) = default;
- UptrVectorIterator& operator=(const UptrVectorIterator&) = default;
- inline UptrVectorIterator& operator++();
- inline UptrVectorIterator operator++(int);
- inline UptrVectorIterator& operator--();
- inline UptrVectorIterator operator--(int);
- reference operator*() const { return **iterator_; }
- pointer operator->() { return (*iterator_).get(); }
- reference operator[](ptrdiff_t index) { return **(iterator_ + index); }
- inline bool operator==(const UptrVectorIterator& that) const;
- inline bool operator!=(const UptrVectorIterator& that) const;
- inline ptrdiff_t operator-(const UptrVectorIterator& that) const;
- inline bool operator<(const UptrVectorIterator& that) const;
- // Inserts the given |value| to the position pointed to by this iterator
- // and returns an iterator to the newly iserted |value|.
- // If the underlying vector changes capacity, all previous iterators will be
- // invalidated. Otherwise, those previous iterators pointing to after the
- // insertion point will be invalidated.
- template <bool IsConstForMethod = IsConst>
- inline typename std::enable_if<!IsConstForMethod, UptrVectorIterator>::type
- InsertBefore(Uptr value);
- // Inserts the given |valueVector| to the position pointed to by this iterator
- // and returns an iterator to the first newly inserted value.
- // If the underlying vector changes capacity, all previous iterators will be
- // invalidated. Otherwise, those previous iterators pointing to after the
- // insertion point will be invalidated.
- template <bool IsConstForMethod = IsConst>
- inline typename std::enable_if<!IsConstForMethod, UptrVectorIterator>::type
- InsertBefore(UptrVector* valueVector);
- // Erases the value at the position pointed to by this iterator
- // and returns an iterator to the following value.
- // If the underlying vector changes capacity, all previous iterators will be
- // invalidated. Otherwise, those previous iterators pointing to after the
- // erasure point will be invalidated.
- template <bool IsConstForMethod = IsConst>
- inline typename std::enable_if<!IsConstForMethod, UptrVectorIterator>::type
- Erase();
- // Returns the underlying iterator.
- UnderlyingIterator Get() const { return iterator_; }
- // Returns a valid end iterator for the underlying container.
- UptrVectorIterator End() const {
- return UptrVectorIterator(container_, container_->end());
- }
- private:
- UptrVector* container_; // The container we are manipulating.
- UnderlyingIterator iterator_; // The raw iterator from the container.
- };
- // Handy class for a (begin, end) iterator pair.
- template <typename IteratorType>
- class IteratorRange {
- public:
- IteratorRange(const IteratorType& b, const IteratorType& e)
- : begin_(b), end_(e) {}
- IteratorRange(IteratorType&& b, IteratorType&& e)
- : begin_(std::move(b)), end_(std::move(e)) {}
- IteratorType begin() const { return begin_; }
- IteratorType end() const { return end_; }
- bool empty() const { return begin_ == end_; }
- size_t size() const { return end_ - begin_; }
- private:
- IteratorType begin_;
- IteratorType end_;
- };
- // Returns a (begin, end) iterator pair for the given iterators.
- // The iterators must belong to the same container.
- template <typename IteratorType>
- inline IteratorRange<IteratorType> make_range(const IteratorType& begin,
- const IteratorType& end) {
- return {begin, end};
- }
- // Returns a (begin, end) iterator pair for the given iterators.
- // The iterators must belong to the same container.
- template <typename IteratorType>
- inline IteratorRange<IteratorType> make_range(IteratorType&& begin,
- IteratorType&& end) {
- return {std::forward<IteratorType>(begin), std::forward<IteratorType>(end)};
- }
- // Returns a (begin, end) iterator pair for the given container.
- template <typename ValueType,
- class IteratorType = UptrVectorIterator<ValueType>>
- inline IteratorRange<IteratorType> make_range(
- std::vector<std::unique_ptr<ValueType>>& container) {
- return {IteratorType(&container, container.begin()),
- IteratorType(&container, container.end())};
- }
- // Returns a const (begin, end) iterator pair for the given container.
- template <typename ValueType,
- class IteratorType = UptrVectorIterator<ValueType, true>>
- inline IteratorRange<IteratorType> make_const_range(
- const std::vector<std::unique_ptr<ValueType>>& container) {
- return {IteratorType(&container, container.cbegin()),
- IteratorType(&container, container.cend())};
- }
- // Wrapping iterator class that only consider elements that satisfy the given
- // predicate |Predicate|. When moving to the next element of the iterator, the
- // FilterIterator will iterate over the range until it finds an element that
- // satisfies |Predicate| or reaches the end of the iterator.
- //
- // Currently this iterator is always an input iterator.
- template <typename SubIterator, typename Predicate>
- class FilterIterator {
- public:
- // Iterator interface.
- using iterator_category = typename SubIterator::iterator_category;
- using value_type = typename SubIterator::value_type;
- using pointer = typename SubIterator::pointer;
- using reference = typename SubIterator::reference;
- using difference_type = typename SubIterator::difference_type;
- using Range = IteratorRange<FilterIterator>;
- FilterIterator(const IteratorRange<SubIterator>& iteration_range,
- Predicate predicate)
- : cur_(iteration_range.begin()),
- end_(iteration_range.end()),
- predicate_(predicate) {
- if (!IsPredicateSatisfied()) {
- MoveToNextPosition();
- }
- }
- FilterIterator(const SubIterator& end, Predicate predicate)
- : FilterIterator({end, end}, predicate) {}
- inline FilterIterator& operator++() {
- MoveToNextPosition();
- return *this;
- }
- inline FilterIterator operator++(int) {
- FilterIterator old = *this;
- MoveToNextPosition();
- return old;
- }
- reference operator*() const { return *cur_; }
- pointer operator->() { return &*cur_; }
- inline bool operator==(const FilterIterator& rhs) const {
- return cur_ == rhs.cur_ && end_ == rhs.end_;
- }
- inline bool operator!=(const FilterIterator& rhs) const {
- return !(*this == rhs);
- }
- // Returns the underlying iterator.
- SubIterator Get() const { return cur_; }
- // Returns the sentinel iterator.
- FilterIterator GetEnd() const { return FilterIterator(end_, predicate_); }
- private:
- // Returns true if the predicate is satisfied or the current iterator reached
- // the end.
- bool IsPredicateSatisfied() { return cur_ == end_ || predicate_(*cur_); }
- void MoveToNextPosition() {
- if (cur_ == end_) return;
- do {
- ++cur_;
- } while (!IsPredicateSatisfied());
- }
- SubIterator cur_;
- SubIterator end_;
- Predicate predicate_;
- };
- template <typename SubIterator, typename Predicate>
- FilterIterator<SubIterator, Predicate> MakeFilterIterator(
- const IteratorRange<SubIterator>& sub_iterator_range, Predicate predicate) {
- return FilterIterator<SubIterator, Predicate>(sub_iterator_range, predicate);
- }
- template <typename SubIterator, typename Predicate>
- FilterIterator<SubIterator, Predicate> MakeFilterIterator(
- const SubIterator& begin, const SubIterator& end, Predicate predicate) {
- return MakeFilterIterator(make_range(begin, end), predicate);
- }
- template <typename SubIterator, typename Predicate>
- typename FilterIterator<SubIterator, Predicate>::Range MakeFilterIteratorRange(
- const SubIterator& begin, const SubIterator& end, Predicate predicate) {
- return typename FilterIterator<SubIterator, Predicate>::Range(
- MakeFilterIterator(begin, end, predicate),
- MakeFilterIterator(end, end, predicate));
- }
- template <typename VT, bool IC>
- inline UptrVectorIterator<VT, IC>& UptrVectorIterator<VT, IC>::operator++() {
- ++iterator_;
- return *this;
- }
- template <typename VT, bool IC>
- inline UptrVectorIterator<VT, IC> UptrVectorIterator<VT, IC>::operator++(int) {
- auto it = *this;
- ++(*this);
- return it;
- }
- template <typename VT, bool IC>
- inline UptrVectorIterator<VT, IC>& UptrVectorIterator<VT, IC>::operator--() {
- --iterator_;
- return *this;
- }
- template <typename VT, bool IC>
- inline UptrVectorIterator<VT, IC> UptrVectorIterator<VT, IC>::operator--(int) {
- auto it = *this;
- --(*this);
- return it;
- }
- template <typename VT, bool IC>
- inline bool UptrVectorIterator<VT, IC>::operator==(
- const UptrVectorIterator& that) const {
- return container_ == that.container_ && iterator_ == that.iterator_;
- }
- template <typename VT, bool IC>
- inline bool UptrVectorIterator<VT, IC>::operator!=(
- const UptrVectorIterator& that) const {
- return !(*this == that);
- }
- template <typename VT, bool IC>
- inline ptrdiff_t UptrVectorIterator<VT, IC>::operator-(
- const UptrVectorIterator& that) const {
- assert(container_ == that.container_);
- return iterator_ - that.iterator_;
- }
- template <typename VT, bool IC>
- inline bool UptrVectorIterator<VT, IC>::operator<(
- const UptrVectorIterator& that) const {
- assert(container_ == that.container_);
- return iterator_ < that.iterator_;
- }
- template <typename VT, bool IC>
- template <bool IsConstForMethod>
- inline
- typename std::enable_if<!IsConstForMethod, UptrVectorIterator<VT, IC>>::type
- UptrVectorIterator<VT, IC>::InsertBefore(Uptr value) {
- auto index = iterator_ - container_->begin();
- container_->insert(iterator_, std::move(value));
- return UptrVectorIterator(container_, container_->begin() + index);
- }
- template <typename VT, bool IC>
- template <bool IsConstForMethod>
- inline
- typename std::enable_if<!IsConstForMethod, UptrVectorIterator<VT, IC>>::type
- UptrVectorIterator<VT, IC>::InsertBefore(UptrVector* values) {
- const auto pos = iterator_ - container_->begin();
- const auto origsz = container_->size();
- container_->resize(origsz + values->size());
- std::move_backward(container_->begin() + pos, container_->begin() + origsz,
- container_->end());
- std::move(values->begin(), values->end(), container_->begin() + pos);
- return UptrVectorIterator(container_, container_->begin() + pos);
- }
- template <typename VT, bool IC>
- template <bool IsConstForMethod>
- inline
- typename std::enable_if<!IsConstForMethod, UptrVectorIterator<VT, IC>>::type
- UptrVectorIterator<VT, IC>::Erase() {
- auto index = iterator_ - container_->begin();
- (void)container_->erase(iterator_);
- return UptrVectorIterator(container_, container_->begin() + index);
- }
- } // namespace opt
- } // namespace spvtools
- #endif // SOURCE_OPT_ITERATOR_H_
|