/*
 * Copyright (C) 2021 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 INCLUDE_PERFETTO_EXT_BASE_SMALL_VECTOR_H_
#define INCLUDE_PERFETTO_EXT_BASE_SMALL_VECTOR_H_

#include <algorithm>
#include <type_traits>
#include <utility>

#include "perfetto/base/compiler.h"
#include "perfetto/base/logging.h"
#include "perfetto/ext/base/utils.h"

namespace perfetto {
namespace base {

// Uses inline storage first, switches to dynamic storage when it overflows.
template <typename T, size_t kSize>
class SmallVector {
 public:
  static constexpr size_t kInlineSize = kSize;

  explicit SmallVector() = default;

  ~SmallVector() {
    clear();
    if (PERFETTO_UNLIKELY(is_using_heap()))
      AlignedFree(begin_);
    begin_ = end_ = end_of_storage_ = nullptr;
  }

  // Move operators.
  SmallVector(SmallVector&& other) noexcept(
      std::is_nothrow_move_constructible<T>::value) {
    if (other.is_using_heap()) {
      // Move the heap content, no need to move the individual objects as their
      // location won't change.
      begin_ = other.begin_;
      end_ = other.end_;
      end_of_storage_ = other.end_of_storage_;
    } else {
      const size_t other_size = other.size();
      PERFETTO_DCHECK(other_size <= capacity());
      for (size_t i = 0; i < other_size; i++) {
        // Move the entries and destroy the ones in the moved-from object.
        new (&begin_[i]) T(std::move(other.begin_[i]));
        other.begin_[i].~T();
      }
      end_ = begin_ + other_size;
    }
    auto* const other_inline_storage = other.inline_storage_begin();
    other.end_ = other.begin_ = other_inline_storage;
    other.end_of_storage_ = other_inline_storage + kInlineSize;
  }

  SmallVector& operator=(SmallVector&& other) noexcept(
      std::is_nothrow_move_constructible<T>::value) {
    this->~SmallVector();
    new (this) SmallVector<T, kSize>(std::move(other));
    return *this;
  }

  // Copy operators.
  SmallVector(const SmallVector& other) {
    const size_t other_size = other.size();
    if (other_size > capacity())
      Grow(other_size);
    // Copy-construct the elements.
    for (size_t i = 0; i < other_size; ++i)
      new (&begin_[i]) T(other.begin_[i]);
    end_ = begin_ + other_size;
  }

  SmallVector& operator=(const SmallVector& other) {
    if (PERFETTO_UNLIKELY(this == &other))
      return *this;
    this->~SmallVector();
    new (this) SmallVector<T, kSize>(other);
    return *this;
  }

  T* data() { return begin_; }
  const T* data() const { return begin_; }

  T* begin() { return begin_; }
  const T* begin() const { return begin_; }

  T* end() { return end_; }
  const T* end() const { return end_; }

  size_t size() const { return static_cast<size_t>(end_ - begin_); }

  bool empty() const { return end_ == begin_; }

  size_t capacity() const {
    return static_cast<size_t>(end_of_storage_ - begin_);
  }

  T& front() {
    PERFETTO_DCHECK(!empty());
    return begin_[0];
  }
  const T& front() const {
    PERFETTO_DCHECK(!empty());
    return begin_[0];
  }

  T& back() {
    PERFETTO_DCHECK(!empty());
    return end_[-1];
  }
  const T& back() const {
    PERFETTO_DCHECK(!empty());
    return end_[-1];
  }

  T& operator[](size_t index) {
    PERFETTO_DCHECK(index < size());
    return begin_[index];
  }

  const T& operator[](size_t index) const {
    PERFETTO_DCHECK(index < size());
    return begin_[index];
  }

  template <typename... Args>
  void emplace_back(Args&&... args) {
    T* end = end_;
    if (PERFETTO_UNLIKELY(end == end_of_storage_))
      end = Grow();
    new (end) T(std::forward<Args>(args)...);
    end_ = end + 1;
  }

  void pop_back() {
    PERFETTO_DCHECK(!empty());
    back().~T();
    --end_;
  }

  // Clear without reverting back to inline storage.
  void clear() {
    while (!empty())
      pop_back();
  }

 private:
  PERFETTO_NO_INLINE T* Grow(size_t desired_capacity = 0) {
    size_t cur_size = size();
    size_t new_capacity = desired_capacity;
    if (desired_capacity <= cur_size)
      new_capacity = std::max(capacity() * 2, size_t(128));
    T* new_storage =
        static_cast<T*>(AlignedAlloc(alignof(T), new_capacity * sizeof(T)));
    for (size_t i = 0; i < cur_size; ++i) {
      // Move the elements into the new heap buffer and destroy the old ones.
      new (&new_storage[i]) T(std::move(begin_[i]));
      begin_[i].~T();
    }
    if (is_using_heap())
      AlignedFree(begin_);
    begin_ = new_storage;
    end_ = new_storage + cur_size;
    end_of_storage_ = new_storage + new_capacity;
    return end_;
  }

  T* inline_storage_begin() { return reinterpret_cast<T*>(&inline_storage_); }
  bool is_using_heap() { return begin_ != inline_storage_begin(); }

  T* begin_ = inline_storage_begin();
  T* end_ = begin_;
  T* end_of_storage_ = begin_ + kInlineSize;

  typename std::aligned_storage<sizeof(T) * kInlineSize, alignof(T)>::type
      inline_storage_;
};

}  // namespace base
}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_EXT_BASE_SMALL_VECTOR_H_
