/*
 * 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:
  using iterator_category = std::random_access_iterator_tag;
  using value_type = T;
  using difference_type = ptrdiff_t;
  using pointer = value_type*;
  using reference = value_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_
