/*
 * Copyright (C) 2014 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_RUNTIME_BASE_ARRAY_REF_H_
#define ART_RUNTIME_BASE_ARRAY_REF_H_

#include <type_traits>
#include <vector>

#include "base/logging.h"

namespace art {

/**
 * @brief A container that references an array.
 *
 * @details The template class ArrayRef provides a container that references
 * an external array. This external array must remain alive while the ArrayRef
 * object is in use. The external array may be a std::vector<>-backed storage
 * or any other contiguous chunk of memory but that memory must remain valid,
 * i.e. the std::vector<> must not be resized for example.
 *
 * Except for copy/assign and insert/erase/capacity functions, the interface
 * is essentially the same as std::vector<>. Since we don't want to throw
 * exceptions, at() is also excluded.
 */
template <typename T>
class ArrayRef {
 public:
  typedef T value_type;
  typedef T& reference;
  typedef const T& const_reference;
  typedef T* pointer;
  typedef const T* const_pointer;
  typedef T* iterator;
  typedef const T* const_iterator;
  typedef std::reverse_iterator<iterator> reverse_iterator;
  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
  typedef ptrdiff_t difference_type;
  typedef size_t size_type;

  // Constructors.

  constexpr ArrayRef()
      : array_(nullptr), size_(0u) {
  }

  template <size_t size>
  explicit constexpr ArrayRef(T (&array)[size])
      : array_(array), size_(size) {
  }

  template <typename U,
            size_t size,
            typename = typename std::enable_if<std::is_same<T, const U>::value>::type>
  explicit constexpr ArrayRef(U (&array)[size])
      : array_(array), size_(size) {
  }

  constexpr ArrayRef(T* array_in, size_t size_in)
      : array_(array_in), size_(size_in) {
  }

  template <typename Vector,
            typename = typename std::enable_if<
                std::is_same<typename Vector::value_type, value_type>::value>::type>
  explicit ArrayRef(Vector& v)
      : array_(v.data()), size_(v.size()) {
  }

  template <typename Vector,
            typename = typename std::enable_if<
                std::is_same<
                    typename std::add_const<typename Vector::value_type>::type,
                    value_type>::value>::type>
  explicit ArrayRef(const Vector& v)
      : array_(v.data()), size_(v.size()) {
  }

  ArrayRef(const ArrayRef&) = default;

  // Assignment operators.

  ArrayRef& operator=(const ArrayRef& other) {
    array_ = other.array_;
    size_ = other.size_;
    return *this;
  }

  template <typename U>
  typename std::enable_if<std::is_same<T, const U>::value, ArrayRef>::type&
  operator=(const ArrayRef<U>& other) {
    return *this = ArrayRef(other);
  }

  // Destructor.
  ~ArrayRef() = default;

  // Iterators.
  iterator begin() { return array_; }
  const_iterator begin() const { return array_; }
  const_iterator cbegin() const { return array_; }
  iterator end() { return array_ + size_; }
  const_iterator end() const { return array_ + size_; }
  const_iterator cend() const { return array_ + size_; }
  reverse_iterator rbegin() { return reverse_iterator(end()); }
  const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
  const_reverse_iterator crbegin() const { return const_reverse_iterator(cend()); }
  reverse_iterator rend() { return reverse_iterator(begin()); }
  const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
  const_reverse_iterator crend() const { return const_reverse_iterator(cbegin()); }

  // Size.
  size_type size() const { return size_; }
  bool empty() const { return size() == 0u; }

  // Element access. NOTE: Not providing at().

  reference operator[](size_type n) {
    DCHECK_LT(n, size_);
    return array_[n];
  }

  const_reference operator[](size_type n) const {
    DCHECK_LT(n, size_);
    return array_[n];
  }

  reference front() {
    DCHECK_NE(size_, 0u);
    return array_[0];
  }

  const_reference front() const {
    DCHECK_NE(size_, 0u);
    return array_[0];
  }

  reference back() {
    DCHECK_NE(size_, 0u);
    return array_[size_ - 1u];
  }

  const_reference back() const {
    DCHECK_NE(size_, 0u);
    return array_[size_ - 1u];
  }

  value_type* data() { return array_; }
  const value_type* data() const { return array_; }

  ArrayRef SubArray(size_type pos) {
    return SubArray(pos, size() - pos);
  }
  ArrayRef<const T> SubArray(size_type pos) const {
    return SubArray(pos, size() - pos);
  }
  ArrayRef SubArray(size_type pos, size_type length) {
    DCHECK_LE(pos, size());
    DCHECK_LE(length, size() - pos);
    return ArrayRef(data() + pos, length);
  }
  ArrayRef<const T> SubArray(size_type pos, size_type length) const {
    DCHECK_LE(pos, size());
    DCHECK_LE(length, size() - pos);
    return ArrayRef<const T>(data() + pos, length);
  }

 private:
  T* array_;
  size_t size_;
};

template <typename T>
bool operator==(const ArrayRef<T>& lhs, const ArrayRef<T>& rhs) {
  return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
}

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

}  // namespace art


#endif  // ART_RUNTIME_BASE_ARRAY_REF_H_
