1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ART_LIBARTBASE_BASE_STRIDE_ITERATOR_H_
18 #define ART_LIBARTBASE_BASE_STRIDE_ITERATOR_H_
19 
20 #include <iterator>
21 
22 #include <android-base/logging.h>
23 
24 namespace art {
25 
26 template<typename T>
27 class StrideIterator : public std::iterator<std::random_access_iterator_tag, T> {
28  public:
29   using difference_type =
30       typename std::iterator<std::random_access_iterator_tag, T>::difference_type;
31 
32   StrideIterator(const StrideIterator&) = default;
33   StrideIterator(StrideIterator&&) = default;
34   StrideIterator& operator=(const StrideIterator&) = default;
35   StrideIterator& operator=(StrideIterator&&) = default;
36 
37   StrideIterator(T* ptr, size_t stride)
38       : ptr_(reinterpret_cast<uintptr_t>(ptr)),
39         stride_(stride) {}
40 
41   bool operator==(const StrideIterator& other) const {
42     DCHECK_EQ(stride_, other.stride_);
43     return ptr_ == other.ptr_;
44   }
45 
46   bool operator!=(const StrideIterator& other) const {
47     return !(*this == other);
48   }
49 
50   StrideIterator& operator++() {  // Value after modification.
51     ptr_ += stride_;
52     return *this;
53   }
54 
55   StrideIterator operator++(int) {
56     StrideIterator<T> temp = *this;
57     ++*this;
58     return temp;
59   }
60 
61   StrideIterator& operator--() {  // Value after modification.
62     ptr_ -= stride_;
63     return *this;
64   }
65 
66   StrideIterator operator--(int) {
67     StrideIterator<T> temp = *this;
68     --*this;
69     return temp;
70   }
71 
72   StrideIterator& operator+=(difference_type delta) {
73     ptr_ += static_cast<ssize_t>(stride_) * delta;
74     return *this;
75   }
76 
77   StrideIterator operator+(difference_type delta) const {
78     StrideIterator<T> temp = *this;
79     temp += delta;
80     return temp;
81   }
82 
83   StrideIterator& operator-=(difference_type delta) {
84     ptr_ -= static_cast<ssize_t>(stride_) * delta;
85     return *this;
86   }
87 
88   StrideIterator operator-(difference_type delta) const {
89     StrideIterator<T> temp = *this;
90     temp -= delta;
91     return temp;
92   }
93 
94   difference_type operator-(const StrideIterator& rhs) {
95     DCHECK_EQ(stride_, rhs.stride_);
96     DCHECK_EQ((ptr_ - rhs.ptr_) % stride_, 0u);
97     return (ptr_ - rhs.ptr_) / stride_;
98   }
99 
100   T& operator*() const {
101     return *reinterpret_cast<T*>(ptr_);
102   }
103 
104   T* operator->() const {
105     return &**this;
106   }
107 
108   T& operator[](difference_type n) {
109     return *(*this + n);
110   }
111 
112  private:
113   uintptr_t ptr_;
114   // Not const for operator=.
115   size_t stride_;
116 
117   template <typename U>
118   friend bool operator<(const StrideIterator<U>& lhs, const StrideIterator<U>& rhs);
119 };
120 
121 template <typename T>
122 StrideIterator<T> operator+(typename StrideIterator<T>::difference_type dist,
123                             const StrideIterator<T>& it) {
124   return it + dist;
125 }
126 
127 template <typename T>
128 bool operator<(const StrideIterator<T>& lhs, const StrideIterator<T>& rhs) {
129   DCHECK_EQ(lhs.stride_, rhs.stride_);
130   return lhs.ptr_ < rhs.ptr_;
131 }
132 
133 template <typename T>
134 bool operator>(const StrideIterator<T>& lhs, const StrideIterator<T>& rhs) {
135   return rhs < lhs;
136 }
137 
138 template <typename T>
139 bool operator<=(const StrideIterator<T>& lhs, const StrideIterator<T>& rhs) {
140   return !(rhs < lhs);
141 }
142 
143 template <typename T>
144 bool operator>=(const StrideIterator<T>& lhs, const StrideIterator<T>& rhs) {
145   return !(lhs < rhs);
146 }
147 
148 }  // namespace art
149 
150 #endif  // ART_LIBARTBASE_BASE_STRIDE_ITERATOR_H_
151