// Copyright 2014 The Chromium 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 TOOLS_GN_UNIQUE_VECTOR_H_
#define TOOLS_GN_UNIQUE_VECTOR_H_

#include <stddef.h>
#include <stdint.h>

#include <algorithm>
#include <functional>
#include <vector>

#include "hash_table_base.h"

// A HashTableBase node type used by all UniqueVector<> instantiations.
// The node stores the item's hash value and its index plus 1, in order
// to follow the HashTableBase requirements (i.e. zero-initializable null
// value).
struct UniqueVectorNode {
  uint32_t hash32;
  uint32_t index_plus1;

  size_t hash_value() const { return hash32; }

  bool is_valid() const { return !is_null(); }

  bool is_null() const { return index_plus1 == 0; }

  // Do not support deletion, making lookup faster.
  static constexpr bool is_tombstone() { return false; }

  // Return vector index.
  size_t index() const { return index_plus1 - 1u; }

  static uint32_t ToHash32(size_t hash) { return static_cast<uint32_t>(hash); }

  // Create new instance from hash value and vector index.
  static UniqueVectorNode Make(size_t hash, size_t index) {
    return {ToHash32(hash), static_cast<uint32_t>(index + 1u)};
  }
};

using UniqueVectorHashTableBase = HashTableBase<UniqueVectorNode>;

// A common HashSet implementation used by all UniqueVector instantiations.
class UniqueVectorHashSet : public UniqueVectorHashTableBase {
 public:
  using BaseType = UniqueVectorHashTableBase;
  using Node = BaseType::Node;

  // Specialized Lookup() template function.
  // |hash| is the hash value for |item|.
  // |item| is the item search key being looked up.
  // |vector| is containing vector for existing items.
  //
  // Returns a non-null mutable Node pointer.
  template <typename T, typename EqualTo = std::equal_to<T>>
  Node* Lookup(size_t hash, const T& item, const std::vector<T>& vector) const {
    uint32_t hash32 = Node::ToHash32(hash);
    return BaseType::NodeLookup(hash32, [&](const Node* node) {
      return hash32 == node->hash32 && EqualTo()(vector[node->index()], item);
    });
  }

  // Specialized Insert() function that converts |index| into the proper
  // UniqueVectorKey type.
  void Insert(Node* node, size_t hash, size_t index) {
    *node = Node::Make(hash, index);
    BaseType::UpdateAfterInsert(false);
  }

  void Clear() { NodeClear(); }
};

// An ordered set optimized for GN's usage. Such sets are used to store lists
// of configs and libraries, and are appended to but not randomly inserted
// into.
template <typename T,
          typename Hash = std::hash<T>,
          typename EqualTo = std::equal_to<T>>
class UniqueVector {
 public:
  using Vector = std::vector<T>;
  using iterator = typename Vector::iterator;
  using const_iterator = typename Vector::const_iterator;

  const Vector& vector() const { return vector_; }
  size_t size() const { return vector_.size(); }
  bool empty() const { return vector_.empty(); }
  void clear() {
    vector_.clear();
    set_.Clear();
  }
  void reserve(size_t s) { vector_.reserve(s); }

  const T& operator[](size_t index) const { return vector_[index]; }

  const_iterator begin() const { return vector_.begin(); }
  const_iterator end() const { return vector_.end(); }

  // Extract the vector out of the instance, clearing it at the same time.
  Vector release() {
    Vector result = std::move(vector_);
    clear();
    return result;
  }

  // Returns true if the item was appended, false if it already existed (and
  // thus the vector was not modified).
  bool push_back(const T& t) {
    size_t hash;
    auto* node = Lookup(t, &hash);
    if (node->is_valid()) {
      return false;  // Already have this one.
    }
    vector_.push_back(t);
    set_.Insert(node, hash, vector_.size() - 1);
    return true;
  }

  // Same as above, but moves the item into the vector if possible.
  bool push_back(T&& t) {
    size_t hash = Hash()(t);
    auto* node = Lookup(t, &hash);
    if (node->is_valid()) {
      return false;  // Already have this one.
    }
    vector_.push_back(std::move(t));
    set_.Insert(node, hash, vector_.size() - 1);
    return true;
  }

  // Construct an item in-place if possible. Return true if it was
  // appended, false otherwise.
  template <typename... ARGS>
  bool emplace_back(ARGS... args) {
    return push_back(T{std::forward<ARGS>(args)...});
  }

  // Try to add an item to the vector. Return (true, index) in
  // case of insertion, or (false, index) otherwise. In both cases
  // |index| will be the item's index in the set and will not be
  // kIndexNone. This can be used to implement a map using a
  // UniqueVector<> for keys, and a parallel array for values.
  std::pair<bool, size_t> PushBackWithIndex(const T& t) {
    size_t hash;
    auto* node = Lookup(t, &hash);
    if (node->is_valid()) {
      return {false, node->index()};
    }
    size_t result = vector_.size();
    vector_.push_back(t);
    set_.Insert(node, hash, result);
    return {true, result};
  }

  // Same as above, but moves the item into the set on success.
  std::pair<bool, size_t> PushBackWithIndex(T&& t) {
    size_t hash;
    auto* node = Lookup(t, &hash);
    if (node->is_valid()) {
      return {false, node->index()};
    }
    size_t result = vector_.size();
    vector_.push_back(std::move(t));
    set_.Insert(node, hash, result);
    return {true, result};
  }

  // Construct an item in-place if possible. If a corresponding
  // item is already in the vector, return (false, index), otherwise
  // perform the insertion and return (true, index). In both cases
  // |index| will be the item's index in the vector and will not be
  // kIndexNone.
  template <typename... ARGS>
  std::pair<bool, size_t> EmplaceBackWithIndex(ARGS... args) {
    return PushBackWithIndex(T{std::forward<ARGS>(args)...});
  }

  // Appends a range of items from an iterator.
  template <typename iter>
  void Append(const iter& begin, const iter& end) {
    for (iter i = begin; i != end; ++i)
      push_back(*i);
  }

  // Append from any iterable container with begin() and end()
  // methods, whose iterators derefence to values convertible to T.
  template <typename C,
            typename = std::void_t<
                decltype(static_cast<const T>(*std::declval<C>().begin())),
                decltype(static_cast<const T>(*std::declval<C>().end()))>>
  void Append(const C& other) {
    Append(other.begin(), other.end());
  }

  // Append from any moveable iterable container with begin() and
  // end() methods. This variant moves items from the container
  // into the UniqueVector instance.
  template <typename C,
            typename = std::void_t<
                decltype(static_cast<T>(*std::declval<C>().begin())),
                decltype(static_cast<T>(*std::declval<C>().end()))>>
  void Append(C&& other) {
    for (auto it = other.begin(); it != other.end(); ++it)
      push_back(std::move(*it));
  }

  // Returns true if the item is already in the vector.
  bool Contains(const T& t) const {
    size_t hash;
    return Lookup(t, &hash)->is_valid();
  }

  // Returns the index of the item matching the given value in the list, or
  // kIndexNone if it's not found.
  size_t IndexOf(const T& t) const {
    size_t hash;
    return Lookup(t, &hash)->index();
  }

  static constexpr size_t kIndexNone = 0xffffffffu;

 private:
  // Lookup hash set node for item |t|, also sets |*hash| to the hash value.
  UniqueVectorNode* Lookup(const T& t, size_t* hash) const {
    *hash = Hash()(t);
    return set_.Lookup<T, EqualTo>(*hash, t, vector_);
  }

  Vector vector_;
  UniqueVectorHashSet set_;
};

#endif  // TOOLS_GN_UNIQUE_VECTOR_H_
