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 { 28 public: 29 using iterator_category = std::random_access_iterator_tag; 30 using value_type = T; 31 using difference_type = ptrdiff_t; 32 using pointer = value_type*; 33 using reference = value_type&; 34 35 StrideIterator(const StrideIterator&) = default; 36 StrideIterator(StrideIterator&&) noexcept = default; 37 StrideIterator& operator=(const StrideIterator&) = default; 38 StrideIterator& operator=(StrideIterator&&) noexcept = default; 39 StrideIterator(T * ptr,size_t stride)40 StrideIterator(T* ptr, size_t stride) 41 : ptr_(reinterpret_cast<uintptr_t>(ptr)), 42 stride_(stride) {} 43 44 bool operator==(const StrideIterator& other) const { 45 DCHECK_EQ(stride_, other.stride_); 46 return ptr_ == other.ptr_; 47 } 48 49 bool operator!=(const StrideIterator& other) const { 50 return !(*this == other); 51 } 52 53 StrideIterator& operator++() { // Value after modification. 54 ptr_ += stride_; 55 return *this; 56 } 57 58 StrideIterator operator++(int) { 59 StrideIterator<T> temp = *this; 60 ++*this; 61 return temp; 62 } 63 64 StrideIterator& operator--() { // Value after modification. 65 ptr_ -= stride_; 66 return *this; 67 } 68 69 StrideIterator operator--(int) { 70 StrideIterator<T> temp = *this; 71 --*this; 72 return temp; 73 } 74 75 StrideIterator& operator+=(difference_type delta) { 76 ptr_ += static_cast<ssize_t>(stride_) * delta; 77 return *this; 78 } 79 80 StrideIterator operator+(difference_type delta) const { 81 StrideIterator<T> temp = *this; 82 temp += delta; 83 return temp; 84 } 85 86 StrideIterator& operator-=(difference_type delta) { 87 ptr_ -= static_cast<ssize_t>(stride_) * delta; 88 return *this; 89 } 90 91 StrideIterator operator-(difference_type delta) const { 92 StrideIterator<T> temp = *this; 93 temp -= delta; 94 return temp; 95 } 96 97 difference_type operator-(const StrideIterator& rhs) { 98 DCHECK_EQ(stride_, rhs.stride_); 99 DCHECK_EQ((ptr_ - rhs.ptr_) % stride_, 0u); 100 return (ptr_ - rhs.ptr_) / stride_; 101 } 102 103 T& operator*() const { 104 return *reinterpret_cast<T*>(ptr_); 105 } 106 107 T* operator->() const { 108 return &**this; 109 } 110 111 T& operator[](difference_type n) { 112 return *(*this + n); 113 } 114 115 private: 116 uintptr_t ptr_; 117 // Not const for operator=. 118 size_t stride_; 119 120 template <typename U> 121 friend bool operator<(const StrideIterator<U>& lhs, const StrideIterator<U>& rhs); 122 }; 123 124 template <typename T> 125 StrideIterator<T> operator+(typename StrideIterator<T>::difference_type dist, 126 const StrideIterator<T>& it) { 127 return it + dist; 128 } 129 130 template <typename T> 131 bool operator<(const StrideIterator<T>& lhs, const StrideIterator<T>& rhs) { 132 DCHECK_EQ(lhs.stride_, rhs.stride_); 133 return lhs.ptr_ < rhs.ptr_; 134 } 135 136 template <typename T> 137 bool operator>(const StrideIterator<T>& lhs, const StrideIterator<T>& rhs) { 138 return rhs < lhs; 139 } 140 141 template <typename T> 142 bool operator<=(const StrideIterator<T>& lhs, const StrideIterator<T>& rhs) { 143 return !(rhs < lhs); 144 } 145 146 template <typename T> 147 bool operator>=(const StrideIterator<T>& lhs, const StrideIterator<T>& rhs) { 148 return !(lhs < rhs); 149 } 150 151 } // namespace art 152 153 #endif // ART_LIBARTBASE_BASE_STRIDE_ITERATOR_H_ 154