//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#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 */
