iterator.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  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:
  31. using iterator_category = std::random_access_iterator_tag;
  32. using value_type = ValueType;
  33. using pointer = value_type*;
  34. using reference = value_type&;
  35. using difference_type = std::ptrdiff_t;
  36. // Type aliases. We need to apply constness properly if |IsConst| is true.
  37. using Uptr = std::unique_ptr<ValueType>;
  38. using UptrVector = typename std::conditional<IsConst, const std::vector<Uptr>,
  39. std::vector<Uptr>>::type;
  40. using UnderlyingIterator =
  41. typename std::conditional<IsConst, typename UptrVector::const_iterator,
  42. typename UptrVector::iterator>::type;
  43. // Creates a new iterator from the given |container| and its raw iterator
  44. // |it|.
  45. UptrVectorIterator(UptrVector* container, const UnderlyingIterator& it)
  46. : container_(container), iterator_(it) {}
  47. UptrVectorIterator(const UptrVectorIterator&) = default;
  48. UptrVectorIterator& operator=(const UptrVectorIterator&) = default;
  49. inline UptrVectorIterator& operator++();
  50. inline UptrVectorIterator operator++(int);
  51. inline UptrVectorIterator& operator--();
  52. inline UptrVectorIterator operator--(int);
  53. reference operator*() const { return **iterator_; }
  54. pointer operator->() { return (*iterator_).get(); }
  55. reference operator[](ptrdiff_t index) { return **(iterator_ + index); }
  56. inline bool operator==(const UptrVectorIterator& that) const;
  57. inline bool operator!=(const UptrVectorIterator& that) const;
  58. inline ptrdiff_t operator-(const UptrVectorIterator& that) const;
  59. inline bool operator<(const UptrVectorIterator& that) const;
  60. // Inserts the given |value| to the position pointed to by this iterator
  61. // and returns an iterator to the newly iserted |value|.
  62. // If the underlying vector changes capacity, all previous iterators will be
  63. // invalidated. Otherwise, those previous iterators pointing to after the
  64. // insertion point will be invalidated.
  65. template <bool IsConstForMethod = IsConst>
  66. inline typename std::enable_if<!IsConstForMethod, UptrVectorIterator>::type
  67. InsertBefore(Uptr value);
  68. // Inserts the given |valueVector| to the position pointed to by this iterator
  69. // and returns an iterator to the first newly inserted value.
  70. // If the underlying vector changes capacity, all previous iterators will be
  71. // invalidated. Otherwise, those previous iterators pointing to after the
  72. // insertion point will be invalidated.
  73. template <bool IsConstForMethod = IsConst>
  74. inline typename std::enable_if<!IsConstForMethod, UptrVectorIterator>::type
  75. InsertBefore(UptrVector* valueVector);
  76. // Erases the value at the position pointed to by this iterator
  77. // and returns an iterator to the following value.
  78. // If the underlying vector changes capacity, all previous iterators will be
  79. // invalidated. Otherwise, those previous iterators pointing to after the
  80. // erasure point will be invalidated.
  81. template <bool IsConstForMethod = IsConst>
  82. inline typename std::enable_if<!IsConstForMethod, UptrVectorIterator>::type
  83. Erase();
  84. // Returns the underlying iterator.
  85. UnderlyingIterator Get() const { return iterator_; }
  86. // Returns a valid end iterator for the underlying container.
  87. UptrVectorIterator End() const {
  88. return UptrVectorIterator(container_, container_->end());
  89. }
  90. private:
  91. UptrVector* container_; // The container we are manipulating.
  92. UnderlyingIterator iterator_; // The raw iterator from the container.
  93. };
  94. // Handy class for a (begin, end) iterator pair.
  95. template <typename IteratorType>
  96. class IteratorRange {
  97. public:
  98. IteratorRange(const IteratorType& b, const IteratorType& e)
  99. : begin_(b), end_(e) {}
  100. IteratorRange(IteratorType&& b, IteratorType&& e)
  101. : begin_(std::move(b)), end_(std::move(e)) {}
  102. IteratorType begin() const { return begin_; }
  103. IteratorType end() const { return end_; }
  104. bool empty() const { return begin_ == end_; }
  105. size_t size() const { return end_ - begin_; }
  106. private:
  107. IteratorType begin_;
  108. IteratorType end_;
  109. };
  110. // Returns a (begin, end) iterator pair for the given iterators.
  111. // The iterators must belong to the same container.
  112. template <typename IteratorType>
  113. inline IteratorRange<IteratorType> make_range(const IteratorType& begin,
  114. const IteratorType& end) {
  115. return {begin, end};
  116. }
  117. // Returns a (begin, end) iterator pair for the given iterators.
  118. // The iterators must belong to the same container.
  119. template <typename IteratorType>
  120. inline IteratorRange<IteratorType> make_range(IteratorType&& begin,
  121. IteratorType&& end) {
  122. return {std::forward<IteratorType>(begin), std::forward<IteratorType>(end)};
  123. }
  124. // Returns a (begin, end) iterator pair for the given container.
  125. template <typename ValueType,
  126. class IteratorType = UptrVectorIterator<ValueType>>
  127. inline IteratorRange<IteratorType> make_range(
  128. std::vector<std::unique_ptr<ValueType>>& container) {
  129. return {IteratorType(&container, container.begin()),
  130. IteratorType(&container, container.end())};
  131. }
  132. // Returns a const (begin, end) iterator pair for the given container.
  133. template <typename ValueType,
  134. class IteratorType = UptrVectorIterator<ValueType, true>>
  135. inline IteratorRange<IteratorType> make_const_range(
  136. const std::vector<std::unique_ptr<ValueType>>& container) {
  137. return {IteratorType(&container, container.cbegin()),
  138. IteratorType(&container, container.cend())};
  139. }
  140. // Wrapping iterator class that only consider elements that satisfy the given
  141. // predicate |Predicate|. When moving to the next element of the iterator, the
  142. // FilterIterator will iterate over the range until it finds an element that
  143. // satisfies |Predicate| or reaches the end of the iterator.
  144. //
  145. // Currently this iterator is always an input iterator.
  146. template <typename SubIterator, typename Predicate>
  147. class FilterIterator {
  148. public:
  149. // Iterator interface.
  150. using iterator_category = typename SubIterator::iterator_category;
  151. using value_type = typename SubIterator::value_type;
  152. using pointer = typename SubIterator::pointer;
  153. using reference = typename SubIterator::reference;
  154. using difference_type = typename SubIterator::difference_type;
  155. using Range = IteratorRange<FilterIterator>;
  156. FilterIterator(const IteratorRange<SubIterator>& iteration_range,
  157. Predicate predicate)
  158. : cur_(iteration_range.begin()),
  159. end_(iteration_range.end()),
  160. predicate_(predicate) {
  161. if (!IsPredicateSatisfied()) {
  162. MoveToNextPosition();
  163. }
  164. }
  165. FilterIterator(const SubIterator& end, Predicate predicate)
  166. : FilterIterator({end, end}, predicate) {}
  167. inline FilterIterator& operator++() {
  168. MoveToNextPosition();
  169. return *this;
  170. }
  171. inline FilterIterator operator++(int) {
  172. FilterIterator old = *this;
  173. MoveToNextPosition();
  174. return old;
  175. }
  176. reference operator*() const { return *cur_; }
  177. pointer operator->() { return &*cur_; }
  178. inline bool operator==(const FilterIterator& rhs) const {
  179. return cur_ == rhs.cur_ && end_ == rhs.end_;
  180. }
  181. inline bool operator!=(const FilterIterator& rhs) const {
  182. return !(*this == rhs);
  183. }
  184. // Returns the underlying iterator.
  185. SubIterator Get() const { return cur_; }
  186. // Returns the sentinel iterator.
  187. FilterIterator GetEnd() const { return FilterIterator(end_, predicate_); }
  188. private:
  189. // Returns true if the predicate is satisfied or the current iterator reached
  190. // the end.
  191. bool IsPredicateSatisfied() { return cur_ == end_ || predicate_(*cur_); }
  192. void MoveToNextPosition() {
  193. if (cur_ == end_) return;
  194. do {
  195. ++cur_;
  196. } while (!IsPredicateSatisfied());
  197. }
  198. SubIterator cur_;
  199. SubIterator end_;
  200. Predicate predicate_;
  201. };
  202. template <typename SubIterator, typename Predicate>
  203. FilterIterator<SubIterator, Predicate> MakeFilterIterator(
  204. const IteratorRange<SubIterator>& sub_iterator_range, Predicate predicate) {
  205. return FilterIterator<SubIterator, Predicate>(sub_iterator_range, predicate);
  206. }
  207. template <typename SubIterator, typename Predicate>
  208. FilterIterator<SubIterator, Predicate> MakeFilterIterator(
  209. const SubIterator& begin, const SubIterator& end, Predicate predicate) {
  210. return MakeFilterIterator(make_range(begin, end), predicate);
  211. }
  212. template <typename SubIterator, typename Predicate>
  213. typename FilterIterator<SubIterator, Predicate>::Range MakeFilterIteratorRange(
  214. const SubIterator& begin, const SubIterator& end, Predicate predicate) {
  215. return typename FilterIterator<SubIterator, Predicate>::Range(
  216. MakeFilterIterator(begin, end, predicate),
  217. MakeFilterIterator(end, end, predicate));
  218. }
  219. template <typename VT, bool IC>
  220. inline UptrVectorIterator<VT, IC>& UptrVectorIterator<VT, IC>::operator++() {
  221. ++iterator_;
  222. return *this;
  223. }
  224. template <typename VT, bool IC>
  225. inline UptrVectorIterator<VT, IC> UptrVectorIterator<VT, IC>::operator++(int) {
  226. auto it = *this;
  227. ++(*this);
  228. return it;
  229. }
  230. template <typename VT, bool IC>
  231. inline UptrVectorIterator<VT, IC>& UptrVectorIterator<VT, IC>::operator--() {
  232. --iterator_;
  233. return *this;
  234. }
  235. template <typename VT, bool IC>
  236. inline UptrVectorIterator<VT, IC> UptrVectorIterator<VT, IC>::operator--(int) {
  237. auto it = *this;
  238. --(*this);
  239. return it;
  240. }
  241. template <typename VT, bool IC>
  242. inline bool UptrVectorIterator<VT, IC>::operator==(
  243. const UptrVectorIterator& that) const {
  244. return container_ == that.container_ && iterator_ == that.iterator_;
  245. }
  246. template <typename VT, bool IC>
  247. inline bool UptrVectorIterator<VT, IC>::operator!=(
  248. const UptrVectorIterator& that) const {
  249. return !(*this == that);
  250. }
  251. template <typename VT, bool IC>
  252. inline ptrdiff_t UptrVectorIterator<VT, IC>::operator-(
  253. const UptrVectorIterator& that) const {
  254. assert(container_ == that.container_);
  255. return iterator_ - that.iterator_;
  256. }
  257. template <typename VT, bool IC>
  258. inline bool UptrVectorIterator<VT, IC>::operator<(
  259. const UptrVectorIterator& that) const {
  260. assert(container_ == that.container_);
  261. return iterator_ < that.iterator_;
  262. }
  263. template <typename VT, bool IC>
  264. template <bool IsConstForMethod>
  265. inline
  266. typename std::enable_if<!IsConstForMethod, UptrVectorIterator<VT, IC>>::type
  267. UptrVectorIterator<VT, IC>::InsertBefore(Uptr value) {
  268. auto index = iterator_ - container_->begin();
  269. container_->insert(iterator_, std::move(value));
  270. return UptrVectorIterator(container_, container_->begin() + index);
  271. }
  272. template <typename VT, bool IC>
  273. template <bool IsConstForMethod>
  274. inline
  275. typename std::enable_if<!IsConstForMethod, UptrVectorIterator<VT, IC>>::type
  276. UptrVectorIterator<VT, IC>::InsertBefore(UptrVector* values) {
  277. const auto pos = iterator_ - container_->begin();
  278. const auto origsz = container_->size();
  279. container_->resize(origsz + values->size());
  280. std::move_backward(container_->begin() + pos, container_->begin() + origsz,
  281. container_->end());
  282. std::move(values->begin(), values->end(), container_->begin() + pos);
  283. return UptrVectorIterator(container_, container_->begin() + pos);
  284. }
  285. template <typename VT, bool IC>
  286. template <bool IsConstForMethod>
  287. inline
  288. typename std::enable_if<!IsConstForMethod, UptrVectorIterator<VT, IC>>::type
  289. UptrVectorIterator<VT, IC>::Erase() {
  290. auto index = iterator_ - container_->begin();
  291. (void)container_->erase(iterator_);
  292. return UptrVectorIterator(container_, container_->begin() + index);
  293. }
  294. } // namespace opt
  295. } // namespace spvtools
  296. #endif // SOURCE_OPT_ITERATOR_H_