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