//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef USES_ALLOC_TYPES_HPP
#define USES_ALLOC_TYPES_HPP

# include <memory>
# include <cassert>
#include <cstdlib>

#include "test_macros.h"
#include "test_workarounds.h"
#include "type_id.h"

// There are two forms of uses-allocator construction:
//   (1) UA_AllocArg: 'T(allocator_arg_t, Alloc const&, Args&&...)'
//   (2) UA_AllocLast: 'T(Args&&..., Alloc const&)'
// 'UA_None' represents non-uses allocator construction.
enum class UsesAllocatorType {
  UA_None = 0,
  UA_AllocArg = 2,
  UA_AllocLast = 4
};
constexpr UsesAllocatorType UA_None = UsesAllocatorType::UA_None;
constexpr UsesAllocatorType UA_AllocArg = UsesAllocatorType::UA_AllocArg;
constexpr UsesAllocatorType UA_AllocLast = UsesAllocatorType::UA_AllocLast;

inline const char* toString(UsesAllocatorType UA) {
    switch (UA) {
    case UA_None:
        return "UA_None";
    case UA_AllocArg:
        return "UA_AllocArg";
    case UA_AllocLast:
        return "UA_AllocLast";
    default:
    std::abort();
    }
}

#define COMPARE_ALLOC_TYPE(LHS, RHS) CompareVerbose(#LHS, LHS, #RHS, RHS)

inline bool CompareVerbose(const char* LHSString, UsesAllocatorType LHS,
                           const char* RHSString, UsesAllocatorType RHS) {
    if (LHS == RHS)
        return true;
    std::printf("UsesAllocatorType's don't match:\n%s %s\n----------\n%s %s\n",
                LHSString, toString(LHS), RHSString, toString(RHS));
    return false;
}

template <class Alloc, std::size_t N>
class UsesAllocatorV1;
    // Implements form (1) of uses-allocator construction from the specified
    // 'Alloc' type and exactly 'N' additional arguments. It also provides
    // non-uses allocator construction from 'N' arguments. This test type
    // blows up when form (2) of uses-allocator is even considered.

template <class Alloc, std::size_t N>
class UsesAllocatorV2;
    // Implements form (2) of uses-allocator construction from the specified
    // 'Alloc' type and exactly 'N' additional arguments. It also provides
    // non-uses allocator construction from 'N' arguments.

template <class Alloc, std::size_t N>
class UsesAllocatorV3;
    // Implements both form (1) and (2) of uses-allocator construction from
    // the specified 'Alloc' type and exactly 'N' additional arguments. It also
    // provides non-uses allocator construction from 'N' arguments.

template <class Alloc, std::size_t>
class NotUsesAllocator;
    // Implements both form (1) and (2) of uses-allocator construction from
    // the specified 'Alloc' type and exactly 'N' additional arguments. It also
    // provides non-uses allocator construction from 'N' arguments. However
    // 'NotUsesAllocator' never provides a 'allocator_type' typedef so it is
    // never automatically uses-allocator constructed.


template <class ...ArgTypes, class TestType>
bool checkConstruct(TestType& value, UsesAllocatorType form,
                    typename TestType::CtorAlloc const& alloc)
    // Check that 'value' was constructed using the specified 'form' of
    // construction and with the specified 'ArgTypes...'. Additionally
    // check that 'value' was constructed using the specified 'alloc'.
{
    if (form == UA_None) {
        return value.template checkConstruct<ArgTypes&&...>(form);
    } else {
        return value.template checkConstruct<ArgTypes&&...>(form, alloc);
    }
}


template <class ...ArgTypes, class TestType>
bool checkConstruct(TestType& value, UsesAllocatorType form) {
    return value.template checkConstruct<ArgTypes&&...>(form);
}

template <class TestType>
bool checkConstructionEquiv(TestType& T, TestType& U)
    // check that 'T' and 'U' where initialized in the exact same manner.
{
    return T.checkConstructEquiv(U);
}

////////////////////////////////////////////////////////////////////////////////
namespace detail {

template <bool IsZero, size_t N, class ArgList, class ...Args>
struct TakeNImp;

template <class ArgList, class ...Args>
struct TakeNImp<true, 0, ArgList, Args...> {
  typedef ArgList type;
};

template <size_t N, class ...A1, class F, class ...R>
struct TakeNImp<false, N, ArgumentListID<A1...>, F, R...>
    : TakeNImp<N-1 == 0, N - 1, ArgumentListID<A1..., F>, R...> {};

template <size_t N, class ...Args>
struct TakeNArgs : TakeNImp<N == 0, N, ArgumentListID<>, Args...> {};

template <class T>
struct Identity { typedef T type; };

template <class T>
using IdentityT = typename Identity<T>::type;

template <bool Value>
using EnableIfB = typename std::enable_if<Value, bool>::type;

} // end namespace detail

// FIXME: UsesAllocatorTestBase needs some special logic to deal with
// polymorphic allocators. However we don't want to include
// <experimental/memory_resource> in this header. Therefore in order
// to inject this behavior later we use a trait.
// See test_memory_resource.hpp for more info.
template <class Alloc>
struct TransformErasedTypeAlloc {
  using type = Alloc;
};

using detail::EnableIfB;

struct AllocLastTag {};

template <class Alloc, bool = std::is_default_constructible<Alloc>::value>
struct UsesAllocatorTestBaseStorage {
    Alloc allocator;
    UsesAllocatorTestBaseStorage() = default;
    UsesAllocatorTestBaseStorage(Alloc const& a) : allocator(a) {}
    const Alloc* get_allocator() const { return &allocator; }
};

template <class Alloc>
struct UsesAllocatorTestBaseStorage<Alloc, false> {
  union {
    char dummy;
    Alloc alloc;
  };
  bool has_alloc = false;

  UsesAllocatorTestBaseStorage() : dummy(), has_alloc(false) {}
  UsesAllocatorTestBaseStorage(Alloc const& a) : alloc(a), has_alloc(true) {}
  ~UsesAllocatorTestBaseStorage() {
      if (has_alloc)
          alloc.~Alloc();
  }

  Alloc const* get_allocator() const {
      if (!has_alloc)
          return nullptr;
      return &alloc;
  }
};

template <class Self, class Alloc>
struct UsesAllocatorTestBase {
public:
    using CtorAlloc = typename TransformErasedTypeAlloc<Alloc>::type;

    template <class ...ArgTypes>
    bool checkConstruct(UsesAllocatorType expectType) const {
        auto expectArgs = &makeArgumentID<ArgTypes...>();
        return COMPARE_ALLOC_TYPE(expectType, constructor_called) &&
               COMPARE_TYPEID(args_id, expectArgs);
    }

    template <class ...ArgTypes>
    bool checkConstruct(UsesAllocatorType expectType,
                        CtorAlloc const& expectAlloc) const {
        auto ExpectID = &makeArgumentID<ArgTypes...>() ;
        return COMPARE_ALLOC_TYPE(expectType, constructor_called) &&
               COMPARE_TYPEID(args_id, ExpectID) &&
               has_alloc() && expectAlloc == *get_alloc();

    }

    bool checkConstructEquiv(UsesAllocatorTestBase& O) const {
        if (has_alloc() != O.has_alloc())
            return false;
        return COMPARE_ALLOC_TYPE(constructor_called, O.constructor_called)
            && COMPARE_TYPEID(args_id, O.args_id)
            && (!has_alloc() || *get_alloc() == *O.get_alloc());
    }

protected:
    explicit UsesAllocatorTestBase(const TypeID* aid)
        : args_id(aid), constructor_called(UA_None), alloc_store()
    {}

    UsesAllocatorTestBase(UsesAllocatorTestBase const&)
        : args_id(&makeArgumentID<Self const&>()), constructor_called(UA_None),
          alloc_store()
    {}

    UsesAllocatorTestBase(UsesAllocatorTestBase&&)
        : args_id(&makeArgumentID<Self&&>()), constructor_called(UA_None),
          alloc_store()
    {}

    template <class ...Args>
    UsesAllocatorTestBase(std::allocator_arg_t, CtorAlloc const& a, Args&&...)
        : args_id(&makeArgumentID<Args&&...>()),
          constructor_called(UA_AllocArg),
          alloc_store(a)
    {}

    template <class ...Args, class ArgsIDL = detail::TakeNArgs<sizeof...(Args) - 1, Args&&...>>
    UsesAllocatorTestBase(AllocLastTag, Args&&... args)
        : args_id(&makeTypeIDImp<typename ArgsIDL::type>()),
          constructor_called(UA_AllocLast),
          alloc_store(UsesAllocatorTestBase::getAllocatorFromPack(
            typename ArgsIDL::type{},
            std::forward<Args>(args)...))
    {
    }

private:
    template <class ...LArgs, class ...Args>
    static CtorAlloc getAllocatorFromPack(ArgumentListID<LArgs...>, Args&&... args) {
        return UsesAllocatorTestBase::getAllocatorFromPackImp<LArgs const&...>(args...);
    }

    template <class ...LArgs>
    static CtorAlloc getAllocatorFromPackImp(
        typename detail::Identity<LArgs>::type..., CtorAlloc const& alloc) {
        return alloc;
    }

    bool has_alloc() const { return alloc_store.get_allocator() != nullptr; }
    const CtorAlloc *get_alloc() const { return alloc_store.get_allocator(); }
public:
    const TypeID* args_id;
    UsesAllocatorType constructor_called = UA_None;
    UsesAllocatorTestBaseStorage<CtorAlloc> alloc_store;
};

template <class Alloc, size_t Arity>
class UsesAllocatorV1 : public UsesAllocatorTestBase<UsesAllocatorV1<Alloc, Arity>, Alloc>
{
public:
    typedef Alloc allocator_type;

    using Base = UsesAllocatorTestBase<UsesAllocatorV1, Alloc>;
    using CtorAlloc = typename Base::CtorAlloc;

    UsesAllocatorV1() : Base(&makeArgumentID<>()) {}

    UsesAllocatorV1(UsesAllocatorV1 const&)
        : Base(&makeArgumentID<UsesAllocatorV1 const&>()) {}
    UsesAllocatorV1(UsesAllocatorV1 &&)
        : Base(&makeArgumentID<UsesAllocatorV1 &&>()) {}
    // Non-Uses Allocator Ctor
    template <class ...Args, EnableIfB<sizeof...(Args) == Arity> = false>
    UsesAllocatorV1(Args&&...) : Base(&makeArgumentID<Args&&...>()) {}

    // Uses Allocator Arg Ctor
    template <class ...Args>
    UsesAllocatorV1(std::allocator_arg_t tag, CtorAlloc const & a, Args&&... args)
        : Base(tag, a, std::forward<Args>(args)...)
    { }

    // BLOWS UP: Uses Allocator Last Ctor
    template <class First, class ...Args, EnableIfB<sizeof...(Args) == Arity> Dummy = false>
    constexpr UsesAllocatorV1(First&&, Args&&...)
    {
        static_assert(!std::is_same<First, First>::value, "");
    }
};


template <class Alloc, size_t Arity>
class UsesAllocatorV2 : public UsesAllocatorTestBase<UsesAllocatorV2<Alloc, Arity>, Alloc>
{
public:
    typedef Alloc allocator_type;

    using Base = UsesAllocatorTestBase<UsesAllocatorV2, Alloc>;
    using CtorAlloc = typename Base::CtorAlloc;

    UsesAllocatorV2() : Base(&makeArgumentID<>()) {}
    UsesAllocatorV2(UsesAllocatorV2 const&)
        : Base(&makeArgumentID<UsesAllocatorV2 const&>()) {}
    UsesAllocatorV2(UsesAllocatorV2 &&)
        : Base(&makeArgumentID<UsesAllocatorV2 &&>()) {}

    // Non-Uses Allocator Ctor
    template <class ...Args, EnableIfB<sizeof...(Args) == Arity> = false>
    UsesAllocatorV2(Args&&...) : Base(&makeArgumentID<Args&&...>()) {}

    // Uses Allocator Last Ctor
    template <class ...Args, EnableIfB<sizeof...(Args) == Arity + 1> = false>
    UsesAllocatorV2(Args&&... args)
        : Base(AllocLastTag{}, std::forward<Args>(args)...)
    {}
};

template <class Alloc, size_t Arity>
class UsesAllocatorV3 : public UsesAllocatorTestBase<UsesAllocatorV3<Alloc, Arity>, Alloc>
{
public:
    typedef Alloc allocator_type;

    using Base = UsesAllocatorTestBase<UsesAllocatorV3, Alloc>;
    using CtorAlloc = typename Base::CtorAlloc;

    UsesAllocatorV3() : Base(&makeArgumentID<>()) {}
    UsesAllocatorV3(UsesAllocatorV3 const&)
        : Base(&makeArgumentID<UsesAllocatorV3 const&>()) {}
    UsesAllocatorV3(UsesAllocatorV3 &&)
        : Base(&makeArgumentID<UsesAllocatorV3 &&>()) {}

    // Non-Uses Allocator Ctor
    template <class ...Args, EnableIfB<sizeof...(Args) == Arity> = false>
    UsesAllocatorV3(Args&&...) : Base(&makeArgumentID<Args&&...>()) {}

    // Uses Allocator Arg Ctor
    template <class ...Args>
    UsesAllocatorV3(std::allocator_arg_t tag, CtorAlloc const& alloc, Args&&... args)
        : Base(tag, alloc, std::forward<Args>(args)...)
    {}

    // Uses Allocator Last Ctor
    template <class ...Args, EnableIfB<sizeof...(Args) == Arity + 1> = false>
    UsesAllocatorV3(Args&&... args)
        : Base(AllocLastTag{}, std::forward<Args>(args)...)
    {}
};

template <class Alloc, size_t Arity>
class NotUsesAllocator : public UsesAllocatorTestBase<NotUsesAllocator<Alloc, Arity>, Alloc>
{
public:
    // no allocator_type typedef provided

    using Base = UsesAllocatorTestBase<NotUsesAllocator, Alloc>;
    using CtorAlloc = typename Base::CtorAlloc;

    NotUsesAllocator() : Base(&makeArgumentID<>()) {}
    NotUsesAllocator(NotUsesAllocator const&)
        : Base(&makeArgumentID<NotUsesAllocator const&>()) {}
    NotUsesAllocator(NotUsesAllocator &&)
        : Base(&makeArgumentID<NotUsesAllocator &&>()) {}
    // Non-Uses Allocator Ctor
    template <class ...Args, EnableIfB<sizeof...(Args) == Arity> = false>
    NotUsesAllocator(Args&&...) : Base(&makeArgumentID<Args&&...>()) {}

    // Uses Allocator Arg Ctor
    template <class ...Args>
    NotUsesAllocator(std::allocator_arg_t tag, CtorAlloc const& alloc, Args&&... args)
        : Base(tag, alloc, std::forward<Args>(args)...)
    {}

    // Uses Allocator Last Ctor
    template <class ...Args, EnableIfB<sizeof...(Args) == Arity + 1> = false>
    NotUsesAllocator(Args&&... args)
        : Base(AllocLastTag{}, std::forward<Args>(args)...)
    {}
};

#endif /* USES_ALLOC_TYPES_HPP */
