iterator.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. // Copyright (c) 2016 Google Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #ifndef SOURCE_OPT_ITERATOR_H_
  15. #define SOURCE_OPT_ITERATOR_H_
  16. #include <cstddef> // for ptrdiff_t
  17. #include <iterator>
  18. #include <memory>
  19. #include <type_traits>
  20. #include <utility>
  21. #include <vector>
  22. namespace spvtools {
  23. namespace opt {
  24. // An ad hoc iterator class for std::vector<std::unique_ptr<|ValueType|>>. The
  25. // purpose of this iterator class is to provide transparent access to those
  26. // std::unique_ptr managed elements in the vector, behaving like we are using
  27. // std::vector<|ValueType|>.
  28. template <typename ValueType, bool IsConst = false>
  29. class UptrVectorIterator
  30. : public std::iterator<std::random_access_iterator_tag,
  31. typename std::conditional<IsConst, const ValueType,
  32. ValueType>::type> {
  33. public:
  34. using super = std::iterator<
  35. std::random_access_iterator_tag,
  36. typename std::conditional<IsConst, const ValueType, ValueType>::type>;
  37. using pointer = typename super::pointer;
  38. using reference = typename super::reference;
  39. using difference_type = typename super::difference_type;
  40. // Type aliases. We need to apply constness properly if |IsConst| is true.
  41. using Uptr = std::unique_ptr<ValueType>;
  42. using UptrVector = typename std::conditional<IsConst, const std::vector<Uptr>,
  43. std::vector<Uptr>>::type;
  44. using UnderlyingIterator =
  45. typename std::conditional<IsConst, typename UptrVector::const_iterator,
  46. typename UptrVector::iterator>::type;
  47. // Creates a new iterator from the given |container| and its raw iterator
  48. // |it|.
  49. UptrVectorIterator(UptrVector* container, const UnderlyingIterator& it)
  50. : container_(container), iterator_(it) {}
  51. UptrVectorIterator(const UptrVectorIterator&) = default;
  52. UptrVectorIterator& operator=(const UptrVectorIterator&) = default;
  53. inline UptrVectorIterator& operator++();
  54. inline UptrVectorIterator operator++(int);
  55. inline UptrVectorIterator& operator--();
  56. inline UptrVectorIterator operator--(int);
  57. reference operator*() const { return **iterator_; }
  58. pointer operator->() { return (*iterator_).get(); }
  59. reference operator[](ptrdiff_t index) { return **(iterator_ + index); }
  60. inline bool operator==(const UptrVectorIterator& that) const;
  61. inline bool operator!=(const UptrVectorIterator& that) const;
  62. inline ptrdiff_t operator-(const UptrVectorIterator& that) const;
  63. inline bool operator<(const UptrVectorIterator& that) const;
  64. // Inserts the given |value| to the position pointed to by this iterator
  65. // and returns an iterator to the newly iserted |value|.
  66. // If the underlying vector changes capacity, all previous iterators will be
  67. // invalidated. Otherwise, those previous iterators pointing to after the
  68. // insertion point will be invalidated.
  69. template <bool IsConstForMethod = IsConst>
  70. inline typename std::enable_if<!IsConstForMethod, UptrVectorIterator>::type
  71. InsertBefore(Uptr value);
  72. // Inserts the given |valueVector| to the position pointed to by this iterator
  73. // and returns an iterator to the first newly inserted value.
  74. // If the underlying vector changes capacity, all previous iterators will be
  75. // invalidated. Otherwise, those previous iterators pointing to after the
  76. // insertion point will be invalidated.
  77. template <bool IsConstForMethod = IsConst>
  78. inline typename std::enable_if<!IsConstForMethod, UptrVectorIterator>::type
  79. InsertBefore(UptrVector* valueVector);
  80. // Erases the value at the position pointed to by this iterator
  81. // and returns an iterator to the following value.
  82. // If the underlying vector changes capacity, all previous iterators will be
  83. // invalidated. Otherwise, those previous iterators pointing to after the
  84. // erasure point will be invalidated.
  85. template <bool IsConstForMethod = IsConst>
  86. inline typename std::enable_if<!IsConstForMethod, UptrVectorIterator>::type
  87. Erase();
  88. // Returns the underlying iterator.
  89. UnderlyingIterator Get() const { return iterator_; }
  90. // Returns a valid end iterator for the underlying container.
  91. UptrVectorIterator End() const {
  92. return UptrVectorIterator(container_, container_->end());
  93. }
  94. private:
  95. UptrVector* container_; // The container we are manipulating.
  96. UnderlyingIterator iterator_; // The raw iterator from the container.
  97. };
  98. // Handy class for a (begin, end) iterator pair.
  99. template <typename IteratorType>
  100. class IteratorRange {
  101. public:
  102. IteratorRange(const IteratorType& b, const IteratorType& e)
  103. : begin_(b), end_(e) {}
  104. IteratorRange(IteratorType&& b, IteratorType&& e)
  105. : begin_(std::move(b)), end_(std::move(e)) {}
  106. IteratorType begin() const { return begin_; }
  107. IteratorType end() const { return end_; }
  108. bool empty() const { return begin_ == end_; }
  109. size_t size() const { return end_ - begin_; }
  110. private:
  111. IteratorType begin_;
  112. IteratorType end_;
  113. };
  114. // Returns a (begin, end) iterator pair for the given iterators.
  115. // The iterators must belong to the same container.
  116. template <typename IteratorType>
  117. inline IteratorRange<IteratorType> make_range(const IteratorType& begin,
  118. const IteratorType& end) {
  119. return {begin, end};
  120. }
  121. // Returns a (begin, end) iterator pair for the given iterators.
  122. // The iterators must belong to the same container.
  123. template <typename IteratorType>
  124. inline IteratorRange<IteratorType> make_range(IteratorType&& begin,
  125. IteratorType&& end) {
  126. return {std::move(begin), std::move(end)};
  127. }
  128. // Returns a (begin, end) iterator pair for the given container.
  129. template <typename ValueType,
  130. class IteratorType = UptrVectorIterator<ValueType>>
  131. inline IteratorRange<IteratorType> make_range(
  132. std::vector<std::unique_ptr<ValueType>>& container) {
  133. return {IteratorType(&container, container.begin()),
  134. IteratorType(&container, container.end())};
  135. }
  136. // Returns a const (begin, end) iterator pair for the given container.
  137. template <typename ValueType,
  138. class IteratorType = UptrVectorIterator<ValueType, true>>
  139. inline IteratorRange<IteratorType> make_const_range(
  140. const std::vector<std::unique_ptr<ValueType>>& container) {
  141. return {IteratorType(&container, container.cbegin()),
  142. IteratorType(&container, container.cend())};
  143. }
  144. // Wrapping iterator class that only consider elements that satisfy the given
  145. // predicate |Predicate|. When moving to the next element of the iterator, the
  146. // FilterIterator will iterate over the range until it finds an element that
  147. // satisfies |Predicate| or reaches the end of the iterator.
  148. //
  149. // Currently this iterator is always an input iterator.
  150. template <typename SubIterator, typename Predicate>
  151. class FilterIterator
  152. : public std::iterator<
  153. std::input_iterator_tag, typename SubIterator::value_type,
  154. typename SubIterator::difference_type, typename SubIterator::pointer,
  155. typename SubIterator::reference> {
  156. public:
  157. // Iterator interface.
  158. using iterator_category = typename SubIterator::iterator_category;
  159. using value_type = typename SubIterator::value_type;
  160. using pointer = typename SubIterator::pointer;
  161. using reference = typename SubIterator::reference;
  162. using difference_type = typename SubIterator::difference_type;
  163. using Range = IteratorRange<FilterIterator>;
  164. FilterIterator(const IteratorRange<SubIterator>& iteration_range,
  165. Predicate predicate)
  166. : cur_(iteration_range.begin()),
  167. end_(iteration_range.end()),
  168. predicate_(predicate) {
  169. if (!IsPredicateSatisfied()) {
  170. MoveToNextPosition();
  171. }
  172. }
  173. FilterIterator(const SubIterator& end, Predicate predicate)
  174. : FilterIterator({end, end}, predicate) {}
  175. inline FilterIterator& operator++() {
  176. MoveToNextPosition();
  177. return *this;
  178. }
  179. inline FilterIterator operator++(int) {
  180. FilterIterator old = *this;
  181. MoveToNextPosition();
  182. return old;
  183. }
  184. reference operator*() const { return *cur_; }
  185. pointer operator->() { return &*cur_; }
  186. inline bool operator==(const FilterIterator& rhs) const {
  187. return cur_ == rhs.cur_ && end_ == rhs.end_;
  188. }
  189. inline bool operator!=(const FilterIterator& rhs) const {
  190. return !(*this == rhs);
  191. }
  192. // Returns the underlying iterator.
  193. SubIterator Get() const { return cur_; }
  194. // Returns the sentinel iterator.
  195. FilterIterator GetEnd() const { return FilterIterator(end_, predicate_); }
  196. private:
  197. // Returns true if the predicate is satisfied or the current iterator reached
  198. // the end.
  199. bool IsPredicateSatisfied() { return cur_ == end_ || predicate_(*cur_); }
  200. void MoveToNextPosition() {
  201. if (cur_ == end_) return;
  202. do {
  203. ++cur_;
  204. } while (!IsPredicateSatisfied());
  205. }
  206. SubIterator cur_;
  207. SubIterator end_;
  208. Predicate predicate_;
  209. };
  210. template <typename SubIterator, typename Predicate>
  211. FilterIterator<SubIterator, Predicate> MakeFilterIterator(
  212. const IteratorRange<SubIterator>& sub_iterator_range, Predicate predicate) {
  213. return FilterIterator<SubIterator, Predicate>(sub_iterator_range, predicate);
  214. }
  215. template <typename SubIterator, typename Predicate>
  216. FilterIterator<SubIterator, Predicate> MakeFilterIterator(
  217. const SubIterator& begin, const SubIterator& end, Predicate predicate) {
  218. return MakeFilterIterator(make_range(begin, end), predicate);
  219. }
  220. template <typename SubIterator, typename Predicate>
  221. typename FilterIterator<SubIterator, Predicate>::Range MakeFilterIteratorRange(
  222. const SubIterator& begin, const SubIterator& end, Predicate predicate) {
  223. return typename FilterIterator<SubIterator, Predicate>::Range(
  224. MakeFilterIterator(begin, end, predicate),
  225. MakeFilterIterator(end, end, predicate));
  226. }
  227. template <typename VT, bool IC>
  228. inline UptrVectorIterator<VT, IC>& UptrVectorIterator<VT, IC>::operator++() {
  229. ++iterator_;
  230. return *this;
  231. }
  232. template <typename VT, bool IC>
  233. inline UptrVectorIterator<VT, IC> UptrVectorIterator<VT, IC>::operator++(int) {
  234. auto it = *this;
  235. ++(*this);
  236. return it;
  237. }
  238. template <typename VT, bool IC>
  239. inline UptrVectorIterator<VT, IC>& UptrVectorIterator<VT, IC>::operator--() {
  240. --iterator_;
  241. return *this;
  242. }
  243. template <typename VT, bool IC>
  244. inline UptrVectorIterator<VT, IC> UptrVectorIterator<VT, IC>::operator--(int) {
  245. auto it = *this;
  246. --(*this);
  247. return it;
  248. }
  249. template <typename VT, bool IC>
  250. inline bool UptrVectorIterator<VT, IC>::operator==(
  251. const UptrVectorIterator& that) const {
  252. return container_ == that.container_ && iterator_ == that.iterator_;
  253. }
  254. template <typename VT, bool IC>
  255. inline bool UptrVectorIterator<VT, IC>::operator!=(
  256. const UptrVectorIterator& that) const {
  257. return !(*this == that);
  258. }
  259. template <typename VT, bool IC>
  260. inline ptrdiff_t UptrVectorIterator<VT, IC>::operator-(
  261. const UptrVectorIterator& that) const {
  262. assert(container_ == that.container_);
  263. return iterator_ - that.iterator_;
  264. }
  265. template <typename VT, bool IC>
  266. inline bool UptrVectorIterator<VT, IC>::operator<(
  267. const UptrVectorIterator& that) const {
  268. assert(container_ == that.container_);
  269. return iterator_ < that.iterator_;
  270. }
  271. template <typename VT, bool IC>
  272. template <bool IsConstForMethod>
  273. inline
  274. typename std::enable_if<!IsConstForMethod, UptrVectorIterator<VT, IC>>::type
  275. UptrVectorIterator<VT, IC>::InsertBefore(Uptr value) {
  276. auto index = iterator_ - container_->begin();
  277. container_->insert(iterator_, std::move(value));
  278. return UptrVectorIterator(container_, container_->begin() + index);
  279. }
  280. template <typename VT, bool IC>
  281. template <bool IsConstForMethod>
  282. inline
  283. typename std::enable_if<!IsConstForMethod, UptrVectorIterator<VT, IC>>::type
  284. UptrVectorIterator<VT, IC>::InsertBefore(UptrVector* values) {
  285. const auto pos = iterator_ - container_->begin();
  286. const auto origsz = container_->size();
  287. container_->resize(origsz + values->size());
  288. std::move_backward(container_->begin() + pos, container_->begin() + origsz,
  289. container_->end());
  290. std::move(values->begin(), values->end(), container_->begin() + pos);
  291. return UptrVectorIterator(container_, container_->begin() + pos);
  292. }
  293. template <typename VT, bool IC>
  294. template <bool IsConstForMethod>
  295. inline
  296. typename std::enable_if<!IsConstForMethod, UptrVectorIterator<VT, IC>>::type
  297. UptrVectorIterator<VT, IC>::Erase() {
  298. auto index = iterator_ - container_->begin();
  299. (void)container_->erase(iterator_);
  300. return UptrVectorIterator(container_, container_->begin() + index);
  301. }
  302. } // namespace opt
  303. } // namespace spvtools
  304. #endif // SOURCE_OPT_ITERATOR_H_