// Copyright 2018 The Abseil 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
//
//      https://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 ABSL_CONTAINER_INTERNAL_CONTAINER_MEMORY_H_
#define ABSL_CONTAINER_INTERNAL_CONTAINER_MEMORY_H_

#include <cassert>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <memory>
#include <new>
#include <tuple>
#include <type_traits>
#include <utility>

#include "absl/base/config.h"
#include "absl/hash/hash.h"
#include "absl/memory/memory.h"
#include "absl/meta/type_traits.h"
#include "absl/utility/utility.h"

#ifdef ABSL_HAVE_ADDRESS_SANITIZER
#include <sanitizer/asan_interface.h>
#endif

#ifdef ABSL_HAVE_MEMORY_SANITIZER
#include <sanitizer/msan_interface.h>
#endif

namespace absl {
ABSL_NAMESPACE_BEGIN
namespace container_internal {

template <size_t Alignment>
struct alignas(Alignment) AlignedType {
  // When alignment is sufficient for the allocated memory to store pointers,
  // include a pointer member so that swisstable backing arrays end up in the
  // pointer-containing partition for heap partitioning.
  std::conditional_t<(Alignment < alignof(void*)), char, void*> pointer;
};

// Allocates at least n bytes aligned to the specified alignment.
// Alignment must be a power of 2. It must be positive.
//
// Note that many allocators don't honor alignment requirements above certain
// threshold (usually either alignof(std::max_align_t) or alignof(void*)).
// Allocate() doesn't apply alignment corrections. If the underlying allocator
// returns insufficiently alignment pointer, that's what you are going to get.
template <size_t Alignment, class Alloc>
void* Allocate(Alloc* alloc, size_t n) {
  static_assert(Alignment > 0, "");
  assert(n && "n must be positive");
  using M = AlignedType<Alignment>;
  using A = typename std::allocator_traits<Alloc>::template rebind_alloc<M>;
  using AT = typename std::allocator_traits<Alloc>::template rebind_traits<M>;
  // On macOS, "mem_alloc" is a #define with one argument defined in
  // rpc/types.h, so we can't name the variable "mem_alloc" and initialize it
  // with the "foo(bar)" syntax.
  A my_mem_alloc(*alloc);
  void* p = AT::allocate(my_mem_alloc, (n + sizeof(M) - 1) / sizeof(M));
  assert(reinterpret_cast<uintptr_t>(p) % Alignment == 0 &&
         "allocator does not respect alignment");
  return p;
}

// Returns true if the destruction of the value with given Allocator will be
// trivial.
template <class Allocator, class ValueType>
constexpr auto IsDestructionTrivial() {
  constexpr bool result =
      std::is_trivially_destructible_v<ValueType> &&
      std::is_same_v<typename std::allocator_traits<
                         Allocator>::template rebind_alloc<char>,
                     std::allocator<char>>;
  return std::bool_constant<result>();
}

// The pointer must have been previously obtained by calling
// Allocate<Alignment>(alloc, n).
template <size_t Alignment, class Alloc>
void Deallocate(Alloc* alloc, void* p, size_t n) {
  static_assert(Alignment > 0, "");
  assert(n && "n must be positive");
  using M = AlignedType<Alignment>;
  using A = typename std::allocator_traits<Alloc>::template rebind_alloc<M>;
  using AT = typename std::allocator_traits<Alloc>::template rebind_traits<M>;
  // On macOS, "mem_alloc" is a #define with one argument defined in
  // rpc/types.h, so we can't name the variable "mem_alloc" and initialize it
  // with the "foo(bar)" syntax.
  A my_mem_alloc(*alloc);
  AT::deallocate(my_mem_alloc, static_cast<M*>(p),
                 (n + sizeof(M) - 1) / sizeof(M));
}

namespace memory_internal {

// Constructs T into uninitialized storage pointed by `ptr` using the args
// specified in the tuple.
template <class Alloc, class T, class Tuple, size_t... I>
void ConstructFromTupleImpl(Alloc* alloc, T* ptr, Tuple&& t,
                            std::index_sequence<I...>) {
  std::allocator_traits<Alloc>::construct(
      *alloc, ptr, std::get<I>(std::forward<Tuple>(t))...);
}

template <class T, class F>
struct WithConstructedImplF {
  template <class... Args>
  decltype(std::declval<F>()(std::declval<T>())) operator()(
      Args&&... args) const {
    return std::forward<F>(f)(T(std::forward<Args>(args)...));
  }
  F&& f;
};

template <class T, class Tuple, size_t... Is, class F>
decltype(std::declval<F>()(std::declval<T>())) WithConstructedImpl(
    Tuple&& t, std::index_sequence<Is...>, F&& f) {
  return WithConstructedImplF<T, F>{std::forward<F>(f)}(
      std::get<Is>(std::forward<Tuple>(t))...);
}

template <class T, size_t... Is>
auto TupleRefImpl(T&& t, std::index_sequence<Is...>)
    -> decltype(std::forward_as_tuple(std::get<Is>(std::forward<T>(t))...)) {
  // NOLINTNEXTLINE(bugprone-use-after-move)
  return std::forward_as_tuple(std::get<Is>(std::forward<T>(t))...);
}

// Returns a tuple of references to the elements of the input tuple. T must be a
// tuple.
template <class T>
auto TupleRef(T&& t) -> decltype(TupleRefImpl(
    std::forward<T>(t),
    std::make_index_sequence<std::tuple_size<std::decay_t<T>>::value>())) {
  return TupleRefImpl(
      std::forward<T>(t),
      std::make_index_sequence<std::tuple_size<std::decay_t<T>>::value>());
}

template <class F, class K, class V>
decltype(std::declval<F>()(std::declval<const K&>(), std::piecewise_construct,
                           std::declval<std::tuple<K>>(), std::declval<V>()))
DecomposePairImpl(F&& f, std::pair<std::tuple<K>, V> p) {
  const auto& key = std::get<0>(p.first);
  return std::forward<F>(f)(key, std::piecewise_construct, std::move(p.first),
                            std::move(p.second));
}

}  // namespace memory_internal

// Constructs T into uninitialized storage pointed by `ptr` using the args
// specified in the tuple.
template <class Alloc, class T, class Tuple>
void ConstructFromTuple(Alloc* alloc, T* ptr, Tuple&& t) {
  memory_internal::ConstructFromTupleImpl(
      alloc, ptr, std::forward<Tuple>(t),
      std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>());
}

// Constructs T using the args specified in the tuple and calls F with the
// constructed value.
template <class T, class Tuple, class F>
decltype(std::declval<F>()(std::declval<T>())) WithConstructed(Tuple&& t,
                                                               F&& f) {
  return memory_internal::WithConstructedImpl<T>(
      std::forward<Tuple>(t),
      std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>(),
      std::forward<F>(f));
}

// Given arguments of an std::pair's constructor, PairArgs() returns a pair of
// tuples with references to the passed arguments. The tuples contain
// constructor arguments for the first and the second elements of the pair.
//
// The following two snippets are equivalent.
//
// 1. std::pair<F, S> p(args...);
//
// 2. auto a = PairArgs(args...);
//    std::pair<F, S> p(std::piecewise_construct,
//                      std::move(a.first), std::move(a.second));
inline std::pair<std::tuple<>, std::tuple<>> PairArgs() { return {}; }
template <class F, class S>
std::pair<std::tuple<F&&>, std::tuple<S&&>> PairArgs(F&& f, S&& s) {
  return {std::piecewise_construct, std::forward_as_tuple(std::forward<F>(f)),
          std::forward_as_tuple(std::forward<S>(s))};
}
template <class F, class S>
std::pair<std::tuple<const F&>, std::tuple<const S&>> PairArgs(
    const std::pair<F, S>& p) {
  return PairArgs(p.first, p.second);
}
template <class F, class S>
std::pair<std::tuple<F&&>, std::tuple<S&&>> PairArgs(std::pair<F, S>&& p) {
  return PairArgs(std::forward<F>(p.first), std::forward<S>(p.second));
}
template <class F, class S>
auto PairArgs(std::piecewise_construct_t, F&& f, S&& s)
    -> decltype(std::make_pair(memory_internal::TupleRef(std::forward<F>(f)),
                               memory_internal::TupleRef(std::forward<S>(s)))) {
  return std::make_pair(memory_internal::TupleRef(std::forward<F>(f)),
                        memory_internal::TupleRef(std::forward<S>(s)));
}

// A helper function for implementing apply() in map policies.
template <class F, class... Args>
auto DecomposePair(F&& f, Args&&... args)
    -> decltype(memory_internal::DecomposePairImpl(
        std::forward<F>(f), PairArgs(std::forward<Args>(args)...))) {
  return memory_internal::DecomposePairImpl(
      std::forward<F>(f), PairArgs(std::forward<Args>(args)...));
}

// A helper function for implementing apply() in set policies.
template <class F, class Arg>
decltype(std::declval<F>()(std::declval<const Arg&>(), std::declval<Arg>()))
DecomposeValue(F&& f, Arg&& arg) {
  const auto& key = arg;
  return std::forward<F>(f)(key, std::forward<Arg>(arg));
}

// Helper functions for asan and msan.
inline void SanitizerPoisonMemoryRegion(const void* m, size_t s) {
#ifdef ABSL_HAVE_ADDRESS_SANITIZER
  ASAN_POISON_MEMORY_REGION(m, s);
#endif
#ifdef ABSL_HAVE_MEMORY_SANITIZER
  __msan_poison(m, s);
#endif
  (void)m;
  (void)s;
}

inline void SanitizerUnpoisonMemoryRegion(const void* m, size_t s) {
#ifdef ABSL_HAVE_ADDRESS_SANITIZER
  ASAN_UNPOISON_MEMORY_REGION(m, s);
#endif
#ifdef ABSL_HAVE_MEMORY_SANITIZER
  __msan_unpoison(m, s);
#endif
  (void)m;
  (void)s;
}

template <typename T>
inline void SanitizerPoisonObject(const T* object) {
  SanitizerPoisonMemoryRegion(object, sizeof(T));
}

template <typename T>
inline void SanitizerUnpoisonObject(const T* object) {
  SanitizerUnpoisonMemoryRegion(object, sizeof(T));
}

namespace memory_internal {

// If Pair is a standard-layout type, OffsetOf<Pair>::kFirst and
// OffsetOf<Pair>::kSecond are equivalent to offsetof(Pair, first) and
// offsetof(Pair, second) respectively. Otherwise they are -1.
//
// The purpose of OffsetOf is to avoid calling offsetof() on non-standard-layout
// type, which is non-portable.
template <class Pair, class = std::true_type>
struct OffsetOf {
  static constexpr size_t kFirst = static_cast<size_t>(-1);
  static constexpr size_t kSecond = static_cast<size_t>(-1);
};

template <class Pair>
struct OffsetOf<Pair, typename std::is_standard_layout<Pair>::type> {
  static constexpr size_t kFirst = offsetof(Pair, first);
  static constexpr size_t kSecond = offsetof(Pair, second);
};

template <class K, class V>
struct IsLayoutCompatible {
 private:
  struct Pair {
    K first;
    V second;
  };

  // Is P layout-compatible with Pair?
  template <class P>
  static constexpr bool LayoutCompatible() {
    return std::is_standard_layout<P>() && sizeof(P) == sizeof(Pair) &&
           alignof(P) == alignof(Pair) &&
           memory_internal::OffsetOf<P>::kFirst ==
               memory_internal::OffsetOf<Pair>::kFirst &&
           memory_internal::OffsetOf<P>::kSecond ==
               memory_internal::OffsetOf<Pair>::kSecond;
  }

 public:
  // Whether pair<const K, V> and pair<K, V> are layout-compatible. If they are,
  // then it is safe to store them in a union and read from either.
  static constexpr bool value = std::is_standard_layout<K>() &&
                                std::is_standard_layout<Pair>() &&
                                memory_internal::OffsetOf<Pair>::kFirst == 0 &&
                                LayoutCompatible<std::pair<K, V>>() &&
                                LayoutCompatible<std::pair<const K, V>>();
};

}  // namespace memory_internal

// The internal storage type for key-value containers like flat_hash_map.
//
// It is convenient for the value_type of a flat_hash_map<K, V> to be
// pair<const K, V>; the "const K" prevents accidental modification of the key
// when dealing with the reference returned from find() and similar methods.
// However, this creates other problems; we want to be able to emplace(K, V)
// efficiently with move operations, and similarly be able to move a
// pair<K, V> in insert().
//
// The solution is this union, which aliases the const and non-const versions
// of the pair. This also allows flat_hash_map<const K, V> to work, even though
// that has the same efficiency issues with move in emplace() and insert() -
// but people do it anyway.
//
// If kMutableKeys is false, only the value member can be accessed.
//
// If kMutableKeys is true, key can be accessed through all slots while value
// and mutable_value must be accessed only via INITIALIZED slots. Slots are
// created and destroyed via mutable_value so that the key can be moved later.
//
// Accessing one of the union fields while the other is active is safe as
// long as they are layout-compatible, which is guaranteed by the definition of
// kMutableKeys. For C++11, the relevant section of the standard is
// https://timsong-cpp.github.io/cppwp/n3337/class.mem#19 (9.2.19)
template <class K, class V>
union map_slot_type {
  map_slot_type() {}
  ~map_slot_type() = delete;
  using value_type = std::pair<const K, V>;
  using mutable_value_type =
      std::pair<std::remove_const_t<K>, std::remove_const_t<V>>;

  value_type value;
  mutable_value_type mutable_value;
  std::remove_const_t<K> key;
};

template <class K, class V>
struct map_slot_policy {
  using slot_type = map_slot_type<K, V>;
  using value_type = std::pair<const K, V>;
  using mutable_value_type =
      std::pair<std::remove_const_t<K>, std::remove_const_t<V>>;

 private:
  static void emplace(slot_type* slot) {
    // The construction of union doesn't do anything at runtime but it allows us
    // to access its members without violating aliasing rules.
    new (slot) slot_type;
  }
  // If pair<const K, V> and pair<K, V> are layout-compatible, we can accept one
  // or the other via slot_type. We are also free to access the key via
  // slot_type::key in this case.
  using kMutableKeys = memory_internal::IsLayoutCompatible<K, V>;

 public:
  static value_type& element(slot_type* slot) { return slot->value; }
  static const value_type& element(const slot_type* slot) {
    return slot->value;
  }

  static K& mutable_key(slot_type* slot) {
    // Still check for kMutableKeys so that we can avoid calling std::launder
    // unless necessary because it can interfere with optimizations.
    return kMutableKeys::value ? slot->key
                               : *std::launder(const_cast<K*>(
                                     std::addressof(slot->value.first)));
  }

  static const K& key(const slot_type* slot) {
    return kMutableKeys::value ? slot->key : slot->value.first;
  }

  template <class Allocator, class... Args>
  static void construct(Allocator* alloc, slot_type* slot, Args&&... args) {
    emplace(slot);
    if (kMutableKeys::value) {
      std::allocator_traits<Allocator>::construct(*alloc, &slot->mutable_value,
                                                  std::forward<Args>(args)...);
    } else {
      std::allocator_traits<Allocator>::construct(*alloc, &slot->value,
                                                  std::forward<Args>(args)...);
    }
  }

  // Construct this slot by moving from another slot.
  template <class Allocator>
  static void construct(Allocator* alloc, slot_type* slot, slot_type* other) {
    emplace(slot);
    if (kMutableKeys::value) {
      std::allocator_traits<Allocator>::construct(
          *alloc, &slot->mutable_value, std::move(other->mutable_value));
    } else {
      std::allocator_traits<Allocator>::construct(*alloc, &slot->value,
                                                  std::move(other->value));
    }
  }

  // Construct this slot by copying from another slot.
  template <class Allocator>
  static void construct(Allocator* alloc, slot_type* slot,
                        const slot_type* other) {
    emplace(slot);
    std::allocator_traits<Allocator>::construct(*alloc, &slot->value,
                                                other->value);
  }

  template <class Allocator>
  static auto destroy(Allocator* alloc, slot_type* slot) {
    if (kMutableKeys::value) {
      std::allocator_traits<Allocator>::destroy(*alloc, &slot->mutable_value);
    } else {
      std::allocator_traits<Allocator>::destroy(*alloc, &slot->value);
    }
    return IsDestructionTrivial<Allocator, value_type>();
  }

  template <class Allocator>
  static auto transfer(Allocator* alloc, slot_type* new_slot,
                       slot_type* old_slot) {
    // This should really just be
    // typename absl::is_trivially_relocatable<value_type>::type()
    // but std::pair is not trivially copyable in C++23 in some standard
    // library versions.
    // See https://github.com/llvm/llvm-project/pull/95444 for instance.
    auto is_relocatable = typename std::conjunction<
        absl::is_trivially_relocatable<typename value_type::first_type>,
        absl::is_trivially_relocatable<typename value_type::second_type>>::
        type();

    emplace(new_slot);
    if (is_relocatable) {
      // TODO(b/247130232,b/251814870): remove casts after fixing warnings.
      std::memcpy(static_cast<void*>(std::launder(&new_slot->value)),
                  static_cast<const void*>(&old_slot->value),
                  sizeof(value_type));
      return is_relocatable;
    }

    if (kMutableKeys::value) {
      std::allocator_traits<Allocator>::construct(
          *alloc, &new_slot->mutable_value, std::move(old_slot->mutable_value));
    } else {
      std::allocator_traits<Allocator>::construct(*alloc, &new_slot->value,
                                                  std::move(old_slot->value));
    }
    destroy(alloc, old_slot);
    return is_relocatable;
  }
};

// Suppress erroneous uninitialized memory errors on GCC. For example, GCC
// thinks that the call to slot_array() in find_or_prepare_insert() is reading
// uninitialized memory, but slot_array is only called there when the table is
// non-empty and this memory is initialized when the table is non-empty.
#if !defined(__clang__) && defined(__GNUC__)
#define ABSL_SWISSTABLE_IGNORE_UNINITIALIZED(x)                    \
  _Pragma("GCC diagnostic push")                                   \
      _Pragma("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")  \
          _Pragma("GCC diagnostic ignored \"-Wuninitialized\"") x; \
  _Pragma("GCC diagnostic pop")
#define ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(x) \
  ABSL_SWISSTABLE_IGNORE_UNINITIALIZED(return x)
#else
#define ABSL_SWISSTABLE_IGNORE_UNINITIALIZED(x) x
#define ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(x) return x
#endif

// Variadic arguments hash function that ignore the rest of the arguments.
// Useful for usage with policy traits.
template <class Hash, bool kIsDefault>
struct HashElement {
  HashElement(const Hash& h, size_t s) : hash(h), seed(s) {}

  template <class K, class... Args>
  size_t operator()(const K& key, Args&&...) const {
    if constexpr (kIsDefault) {
      // TODO(b/384509507): resolve `no header providing
      // "absl::hash_internal::SupportsHashWithSeed" is directly included`.
      // Maybe we should make "internal/hash.h" be a separate library.
      return absl::hash_internal::HashWithSeed().hash(hash, key, seed);
    }
    // NOLINTNEXTLINE(clang-diagnostic-sign-conversion)
    return hash(key) ^ seed;
  }
  const Hash& hash;
  size_t seed;
};

// No arguments function hash function for a specific key.
template <class Hash, class Key, bool kIsDefault>
struct HashKey {
  HashKey(const Hash& h, const Key& k) : hash(h), key(k) {}

  size_t operator()(size_t seed) const {
    return HashElement<Hash, kIsDefault>{hash, seed}(key);
  }
  const Hash& hash;
  const Key& key;
};

// Variadic arguments equality function that ignore the rest of the arguments.
// Useful for usage with policy traits.
template <class K1, class KeyEqual>
struct EqualElement {
  template <class K2, class... Args>
  bool operator()(const K2& lhs, Args&&...) const {
    ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(eq(lhs, rhs));
  }
  const K1& rhs;
  const KeyEqual& eq;
};

// Type erased function for computing hash of the slot.
using HashSlotFn = size_t (*)(const void* hash_fn, void* slot, size_t seed);

// Type erased function to apply `Fn` to data inside of the `slot`.
// The data is expected to have type `T`.
template <class Fn, class T, bool kIsDefault>
size_t TypeErasedApplyToSlotFn(const void* fn, void* slot, size_t seed) {
  const auto* f = static_cast<const Fn*>(fn);
  return HashElement<Fn, kIsDefault>{*f, seed}(*static_cast<const T*>(slot));
}

// Type erased function to apply `Fn` to data inside of the `*slot_ptr`.
// The data is expected to have type `T`.
template <class Fn, class T, bool kIsDefault>
size_t TypeErasedDerefAndApplyToSlotFn(const void* fn, void* slot_ptr,
                                       size_t seed) {
  const auto* f = static_cast<const Fn*>(fn);
  const T* slot = *static_cast<T**>(slot_ptr);
  return HashElement<Fn, kIsDefault>{*f, seed}(*slot);
}

// Type erased function to apply `Fn` to data inside of the `slot_ptr->first`.
// The data is expected to have type `T`.
template <class Fn, class T, bool kIsDefault>
size_t TypeErasedDerefAndApplyToSlotFirstFn(const void* fn, void* slot_ptr,
                                            size_t seed) {
  const auto* f = static_cast<const Fn*>(fn);
  const T* slot = *static_cast<T**>(slot_ptr);
  return HashElement<Fn, kIsDefault>{*f, seed}(slot->first);
}

}  // namespace container_internal
ABSL_NAMESPACE_END
}  // namespace absl

#endif  // ABSL_CONTAINER_INTERNAL_CONTAINER_MEMORY_H_
