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