// Copyright 2017-2020 The Verible Authors.
//
// 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.

// This library provides some basic interface extensions to
// iterator_range.

#ifndef VERIBLE_COMMON_UTIL_CONTAINER_ITERATOR_RANGE_H_
#define VERIBLE_COMMON_UTIL_CONTAINER_ITERATOR_RANGE_H_

#include <cstddef>
#include <iterator>  // for std::iterator_traits
#include <utility>   // for std::pair

#include "common/util/iterator_range.h"
#include "common/util/range.h"

namespace verible {

// container_iterator_range provides container-like interfaces to
// an iterator_range (which only has begin() and end()).
// Like iterator_range, this does not own the memory referenced by the range.
// IT is an iterator type.
// Some methods are available for only certain iterator types.
// Any operation on the underlying container that causes internal reallocation
// invalidates these iterator ranges, e.g. vector::push_back().
template <typename IT>
class container_iterator_range : public iterator_range<IT> {
  typedef container_iterator_range<IT> this_type;
  typedef iterator_range<IT> range_type;

 public:
  using iterator = IT;
  using const_iterator = IT;
  using value_type = typename std::iterator_traits<IT>::value_type;
  using reference = typename std::iterator_traits<IT>::reference;

  // Allow default initialization to be usable inside resize-able containers.
  container_iterator_range() = default;

  explicit container_iterator_range(std::pair<IT, IT> p)
      : range_type(std::move(p.first), std::move(p.second)) {}

  // Constructs range from two iterators.
  // To initialize this range to empty, pass the same iterator twice, e.g.
  // container.begin().  This way it will already point to a valid range, and be
  // extendable.
  container_iterator_range(IT b, IT e)
      : range_type(std::move(b), std::move(e)) {}

  bool empty() const { return this->begin() == this->end(); }

  // Returns the number of elements that span this range.
  // The run-time complexity of this depends on that of the underlying iterator.
  size_t size() const { return std::distance(this->begin(), this->end()); }

  // Dereferences first element at begin().
  // Only valid if !this->empty(), just like a vector.
  // Available to bidirectional_iterators.
  reference front() const { return *this->begin(); }

  // Dereferences last element at end() -1.
  // Only valid if !this->empty(), just like a vector.
  // Available to bidirectional_iterators.
  reference back() const {
    auto it = this->end();
    return *(--it);
  }

  // Returns reference to the i'th element.
  // Only available to random-access iterators.
  reference operator[](size_t i) const { return *(this->begin() + i); }

  // Clears this range by moving the end back to the beginning.
  void clear_to_begin() { this->reset(this->begin(), this->begin()); }

  // Clears this range by moving the beginning forward to the end.
  void clear_to_end() { this->reset(this->end(), this->end()); }

  // Sets the lower-bound of this range, which could grow or shrink.
  void set_begin(iterator iter) { this->reset(iter, this->end()); }

  // Sets the upper-bound of this range, which could grow or shrink.
  void set_end(iterator iter) { this->reset(this->begin(), iter); }

  // Grows front-side bound by one element.
  // Caller is responsible for making sure new range still falls within
  // valid backed memory.
  // Available to bidirectional_iterators.
  void extend_front() {
    auto iter = this->begin();
    --iter;
    this->reset(iter, this->end());
  }

  // TODO(fangism): extend_front(N) for random-access iterators

  // Shrink the range from the front-side by one element.
  // Only valid if !this->empty().
  // Available to bidirectional_iterators.
  void pop_front() {
    auto iter = this->begin();
    ++iter;
    this->reset(iter, this->end());
  }

  // TODO(fangism): pop_front(N), like string_view::remove_prefix()

  // Grows back-side bound by one element.
  // Caller is responsible for making sure new range still falls within
  // valid backed memory.
  // Available to bidirectional_iterators.
  void extend_back() {
    auto iter = this->end();
    ++iter;
    this->reset(this->begin(), iter);
  }

  // TODO(fangism): extend_back(N) for random-access iterators

  // Shrink the range from the back-side by one element.
  // Only valid if !this->empty().
  // Available to bidirectional_iterators.
  void pop_back() {
    auto iter = this->end();
    --iter;
    this->reset(this->begin(), iter);
  }

  // TODO(fangism): pop_back(N), like string_view::remove_suffix()

  // TODO(fangism): subrange(N, M), like string_view::substr()

  // Returns true if begin/end bounds of iterator range are identical.
  // Templated to allow comparison between const-mismatched iterators.
  template <typename T2>
  bool operator==(const container_iterator_range<T2>& other) const {
    return BoundsEqual(*this, other);
  }

  template <typename T2>
  bool operator!=(const container_iterator_range<T2>& other) const {
    return !(*this == other);
  }

 protected:
  // Overwrite internal iterators.
  // Provided because they are private (not protected) in base class.
  void reset(iterator b, iterator e) {
    *this = container_iterator_range<IT>(b, e);
  }
};

// Convenience constructor of container_iterator_range,
// analogous to std::make_pair().
template <typename T>
container_iterator_range<T> make_container_range(T x, T y) {
  return container_iterator_range<T>(std::move(x), std::move(y));
}

// Converts std::pair<Iter,Iter> to container_iterator_range<Iter>. E.g.:
//   for (const auto& e : make_container_range(m.equal_range(k))) ...
template <typename Iter>
container_iterator_range<Iter> make_container_range(std::pair<Iter, Iter> p) {
  return container_iterator_range<Iter>(std::move(p));
}

}  // namespace verible

#endif  // VERIBLE_COMMON_UTIL_CONTAINER_ITERATOR_RANGE_H_
