// 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 <algorithm>
#include <unordered_set>
#include <vector>

namespace internal {

// This class allows us to insert things by reference into a hash table which
// avoids copies. The hash function of a UniquifyRef is that of the object it
// points to.
//
// There are two ways it can store data: (1) by (vector*, index) which is used
// to refer to the array in UniqueVector and make it work even when the
// underlying vector is reallocated; (2) by T* which is used to do lookups
// into the hash table of things that aren't in a vector yet.
//
// It also caches the hash value which allows us to query and then insert
// without recomputing the hash.
template <typename T>
class UniquifyRef {
 public:
  UniquifyRef() = default;

  // Initialize with a pointer to a value.
  explicit UniquifyRef(const T* v) : value_(v) { FillHashValue(); }

  // Initialize with an array + index.
  UniquifyRef(const std::vector<T>* v, size_t i) : vect_(v), index_(i) {
    FillHashValue();
  }

  // Initialize with an array + index and a known hash value to prevent
  // re-hashing.
  UniquifyRef(const std::vector<T>* v, size_t i, size_t hash_value)
      : vect_(v), index_(i), hash_val_(hash_value) {}

  const T& value() const { return value_ ? *value_ : (*vect_)[index_]; }
  size_t hash_val() const { return hash_val_; }
  size_t index() const { return index_; }

 private:
  void FillHashValue() {
    std::hash<T> h;
    hash_val_ = h(value());
  }

  // When non-null, points to the object.
  const T* value_ = nullptr;

  // When value is null these are used.
  const std::vector<T>* vect_ = nullptr;
  size_t index_ = static_cast<size_t>(-1);

  size_t hash_val_ = 0;
};

template <typename T>
inline bool operator==(const UniquifyRef<T>& a, const UniquifyRef<T>& b) {
  return a.value() == b.value();
}

template <typename T>
inline bool operator<(const UniquifyRef<T>& a, const UniquifyRef<T>& b) {
  return a.value() < b.value();
}

}  // namespace internal

namespace std {

template <typename T>
struct hash<internal::UniquifyRef<T>> {
  std::size_t operator()(const internal::UniquifyRef<T>& v) const {
    return v.hash_val();
  }
};

}  // namespace std

// 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>
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(); }
  iterator begin() { return vector_.begin(); }
  const_iterator end() const { return vector_.end(); }
  iterator end() { return vector_.end(); }

  // 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) {
    Ref ref(&t);
    if (set_.find(ref) != set_.end())
      return false;  // Already have this one.

    vector_.push_back(t);
    set_.insert(Ref(&vector_, vector_.size() - 1, ref.hash_val()));
    return true;
  }

  bool push_back(T&& t) {
    Ref ref(&t);
    if (set_.find(ref) != set_.end())
      return false;  // Already have this one.

    auto ref_hash_val = ref.hash_val();  // Save across moving t.

    vector_.push_back(std::move(t));  // Invalidates |ref|.
    set_.insert(Ref(&vector_, vector_.size() - 1, ref_hash_val));
    return true;
  }

  // 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);
  }

  // Returns the index of the item matching the given value in the list, or
  // (size_t)(-1) if it's not found.
  size_t IndexOf(const T& t) const {
    Ref ref(&t);
    typename HashSet::const_iterator found = set_.find(ref);
    if (found == set_.end())
      return static_cast<size_t>(-1);
    return found->index();
  }

 private:
  using Ref = internal::UniquifyRef<T>;
  using HashSet = std::unordered_set<Ref>;

  HashSet set_;
  Vector vector_;
};

#endif  // TOOLS_GN_UNIQUE_VECTOR_H_
