/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_LIBARTBASE_BASE_STRIDE_ITERATOR_H_
#define ART_LIBARTBASE_BASE_STRIDE_ITERATOR_H_

#include <iterator>

#include <android-base/logging.h>

namespace art {

template<typename T>
class StrideIterator : public std::iterator<std::random_access_iterator_tag, T> {
 public:
  using difference_type =
      typename std::iterator<std::random_access_iterator_tag, T>::difference_type;

  StrideIterator(const StrideIterator&) = default;
  StrideIterator(StrideIterator&&) noexcept = default;
  StrideIterator& operator=(const StrideIterator&) = default;
  StrideIterator& operator=(StrideIterator&&) noexcept = default;

  StrideIterator(T* ptr, size_t stride)
      : ptr_(reinterpret_cast<uintptr_t>(ptr)),
        stride_(stride) {}

  bool operator==(const StrideIterator& other) const {
    DCHECK_EQ(stride_, other.stride_);
    return ptr_ == other.ptr_;
  }

  bool operator!=(const StrideIterator& other) const {
    return !(*this == other);
  }

  StrideIterator& operator++() {  // Value after modification.
    ptr_ += stride_;
    return *this;
  }

  StrideIterator operator++(int) {
    StrideIterator<T> temp = *this;
    ++*this;
    return temp;
  }

  StrideIterator& operator--() {  // Value after modification.
    ptr_ -= stride_;
    return *this;
  }

  StrideIterator operator--(int) {
    StrideIterator<T> temp = *this;
    --*this;
    return temp;
  }

  StrideIterator& operator+=(difference_type delta) {
    ptr_ += static_cast<ssize_t>(stride_) * delta;
    return *this;
  }

  StrideIterator operator+(difference_type delta) const {
    StrideIterator<T> temp = *this;
    temp += delta;
    return temp;
  }

  StrideIterator& operator-=(difference_type delta) {
    ptr_ -= static_cast<ssize_t>(stride_) * delta;
    return *this;
  }

  StrideIterator operator-(difference_type delta) const {
    StrideIterator<T> temp = *this;
    temp -= delta;
    return temp;
  }

  difference_type operator-(const StrideIterator& rhs) {
    DCHECK_EQ(stride_, rhs.stride_);
    DCHECK_EQ((ptr_ - rhs.ptr_) % stride_, 0u);
    return (ptr_ - rhs.ptr_) / stride_;
  }

  T& operator*() const {
    return *reinterpret_cast<T*>(ptr_);
  }

  T* operator->() const {
    return &**this;
  }

  T& operator[](difference_type n) {
    return *(*this + n);
  }

 private:
  uintptr_t ptr_;
  // Not const for operator=.
  size_t stride_;

  template <typename U>
  friend bool operator<(const StrideIterator<U>& lhs, const StrideIterator<U>& rhs);
};

template <typename T>
StrideIterator<T> operator+(typename StrideIterator<T>::difference_type dist,
                            const StrideIterator<T>& it) {
  return it + dist;
}

template <typename T>
bool operator<(const StrideIterator<T>& lhs, const StrideIterator<T>& rhs) {
  DCHECK_EQ(lhs.stride_, rhs.stride_);
  return lhs.ptr_ < rhs.ptr_;
}

template <typename T>
bool operator>(const StrideIterator<T>& lhs, const StrideIterator<T>& rhs) {
  return rhs < lhs;
}

template <typename T>
bool operator<=(const StrideIterator<T>& lhs, const StrideIterator<T>& rhs) {
  return !(rhs < lhs);
}

template <typename T>
bool operator>=(const StrideIterator<T>& lhs, const StrideIterator<T>& rhs) {
  return !(lhs < rhs);
}

}  // namespace art

#endif  // ART_LIBARTBASE_BASE_STRIDE_ITERATOR_H_
