blob: ba25feae1bfadec062e585626bf845076983dafb [file] [log] [blame]
// 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 LIBSPIRV_OPT_ITERATOR_H_
#define LIBSPIRV_OPT_ITERATOR_H_
#include <iterator>
#include <memory>
#include <type_traits>
#include <vector>
namespace spvtools {
namespace ir {
// 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 std::iterator<
std::random_access_iterator_tag,
typename std::conditional<IsConst, const ValueType, ValueType>::type,
ptrdiff_t> {
public:
using super = std::iterator<
std::random_access_iterator_tag,
typename std::conditional<IsConst, const ValueType, ValueType>::type>;
using pointer = typename super::pointer;
using reference = typename super::reference;
using difference_type = typename super::difference_type;
// 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);
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(IteratorType b, IteratorType e) : begin_(b), end_(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 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())};
}
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);
}
} // namespace ir
} // namespace spvtools
#endif // LIBSPIRV_OPT_ITERATOR_H_