// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_UTILS_SCOPED_LIST_H_
#define V8_UTILS_SCOPED_LIST_H_

#include <type_traits>
#include <vector>

#include "src/base/logging.h"

namespace v8 {
namespace internal {

template <typename T>
class Vector;

template <typename T>
class ZoneList;

// ScopedList is a scope-lifetime list with a std::vector backing that can be
// re-used between ScopedLists. Note that a ScopedList in an outer scope cannot
// add any entries if there is a ScopedList with the same backing in an inner
// scope.
template <typename T, typename TBacking = T>
class ScopedList final {
  // The backing can either be the same type as the list type, or, for pointers,
  // we additionally allow a void* backing store.
  static_assert((std::is_same<TBacking, T>::value) ||
                    (std::is_same<TBacking, void*>::value &&
                     std::is_pointer<T>::value),
                "Incompatible combination of T and TBacking types");

 public:
  explicit ScopedList(std::vector<TBacking>* buffer)
      : buffer_(*buffer), start_(buffer->size()), end_(buffer->size()) {}

  ~ScopedList() { Rewind(); }

  void Rewind() {
    DCHECK_EQ(buffer_.size(), end_);
    buffer_.resize(start_);
    end_ = start_;
  }

  void MergeInto(ScopedList* parent) {
    DCHECK_EQ(parent->end_, start_);
    parent->end_ = end_;
    start_ = end_;
    DCHECK_EQ(0, length());
  }

  int length() const { return static_cast<int>(end_ - start_); }

  const T& at(int i) const {
    size_t index = start_ + i;
    DCHECK_LE(start_, index);
    DCHECK_LT(index, buffer_.size());
    return *reinterpret_cast<T*>(&buffer_[index]);
  }

  T& at(int i) {
    size_t index = start_ + i;
    DCHECK_LE(start_, index);
    DCHECK_LT(index, buffer_.size());
    return *reinterpret_cast<T*>(&buffer_[index]);
  }

  Vector<const T> ToConstVector() const {
    T* data = reinterpret_cast<T*>(buffer_.data() + start_);
    return Vector<const T>(data, length());
  }

  void Add(const T& value) {
    DCHECK_EQ(buffer_.size(), end_);
    buffer_.push_back(value);
    ++end_;
  }

  void AddAll(const Vector<const T>& list) {
    DCHECK_EQ(buffer_.size(), end_);
    buffer_.reserve(buffer_.size() + list.length());
    for (int i = 0; i < list.length(); i++) {
      buffer_.push_back(list.at(i));
    }
    end_ += list.length();
  }

  using iterator = T*;
  using const_iterator = const T*;

  inline iterator begin() {
    return reinterpret_cast<T*>(buffer_.data() + start_);
  }
  inline const_iterator begin() const {
    return reinterpret_cast<T*>(buffer_.data() + start_);
  }

  inline iterator end() { return reinterpret_cast<T*>(buffer_.data() + end_); }
  inline const_iterator end() const {
    return reinterpret_cast<T*>(buffer_.data() + end_);
  }

 private:
  std::vector<TBacking>& buffer_;
  size_t start_;
  size_t end_;
};

template <typename T>
using ScopedPtrList = ScopedList<T*, void*>;

}  // namespace internal
}  // namespace v8

#endif  // V8_UTILS_SCOPED_LIST_H_
