/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#pragma once
#include
#include
#include
#include
#include
#include
namespace ams::sf {
namespace impl {
template
struct IsSmartPointer : public std::false_type{};
template
struct IsSmartPointer> : public std::true_type{};
template
struct IsSmartPointer> : public std::true_type{};
template
struct IsSmartPointer> : public std::true_type{};
template
struct UnmanagedEmplaceImplHolderBaseGetter {
using Type = Impl;
};
template requires (std::is_abstract::value )
struct UnmanagedEmplaceImplHolderBaseGetter {
class Impl2 : public Impl {
public:
using Impl::Impl;
private:
constexpr virtual void AddReference() override { /* ... */ }
constexpr virtual void Release() override { /* ... */ }
};
using Type = Impl2;
};
template
class UnmanagedEmplacedImplHolder {
template
friend class impl::ImplTemplateBaseT;
private:
using Impl2 = typename UnmanagedEmplaceImplHolderBaseGetter::Type;
static_assert(!std::is_abstract::value);
private:
Impl2 m_impl;
private:
template
constexpr explicit UnmanagedEmplacedImplHolder(Args &&... args) : m_impl(std::forward(args)...) { /* ... */ }
public:
static constexpr Impl *GetImplPointer(UnmanagedEmplacedImplHolder *holder) {
return std::addressof(holder->m_impl);
}
};
template
class EmplacedImplHolder : private Impl {
template
friend class impl::ImplTemplateBaseT;
private:
template
constexpr explicit EmplacedImplHolder(Args &&... args) : Impl(std::forward(args)...) { /* ... */ }
public:
static constexpr Impl *GetImplPointer(EmplacedImplHolder *holder) {
return holder;
}
template
static constexpr Impl *GetEmplacedImplPointerImpl(const SharedPointer &sp) {
using Base = impl::ImplTemplateBase;
return static_cast(sp.Get());
}
};
template requires (IsSmartPointer::value)
class EmplacedImplHolder : private Impl {
template
friend class impl::ImplTemplateBaseT;
private:
template
constexpr explicit EmplacedImplHolder(Args &&... args) : Impl(std::forward(args)...) { /* ... */ }
public:
static constexpr auto *GetImplPointer(EmplacedImplHolder *holder) {
return static_cast(holder)->operator ->();
}
template
static constexpr Impl *GetEmplacedImplPointerImpl(const SharedPointer &sp) {
using Base = impl::ImplTemplateBase;
return static_cast(sp.Get());
}
};
template
using SmartPointerHolder = EmplacedImplHolder;
template
class ManagedPointerHolder {
template
friend class impl::ImplTemplateBaseT;
private:
T *m_p;
private:
constexpr explicit ManagedPointerHolder(T *p) : m_p(p) { /* ... */ }
constexpr ~ManagedPointerHolder() { m_p->Release(); }
static constexpr T *GetImplPointer(ManagedPointerHolder *holder) {
return holder->m_p;
}
};
template
class UnmanagedPointerHolder {
template
friend class impl::ImplTemplateBaseT;
private:
T *m_p;
private:
constexpr explicit UnmanagedPointerHolder(T *p) : m_p(p) { /* ... */ }
static constexpr T *GetImplPointer(UnmanagedPointerHolder *holder) {
return holder->m_p;
}
};
}
template
class UnmanagedServiceObject final : public impl::ImplTemplateBase, impl::UnmanagedEmplacedImplHolder> {
private:
using ImplBase = impl::ImplTemplateBase, impl::UnmanagedEmplacedImplHolder>;
public:
using ImplBase::ImplBase;
constexpr virtual void AddReference() override { /* ... */ }
constexpr virtual void Release() override { /* ... */ }
constexpr Impl &GetImpl() { return impl::UnmanagedEmplacedImplHolder::GetImplPointer(this); }
constexpr SharedPointer GetShared() { return SharedPointer(this, false); }
};
template
class UnmanagedServiceObjectByPointer final : public impl::ImplTemplateBase, impl::UnmanagedPointerHolder> {
private:
using ImplBase = impl::ImplTemplateBase, impl::UnmanagedPointerHolder>;
public:
constexpr explicit UnmanagedServiceObjectByPointer(T *ptr) : ImplBase(ptr) { /* ... */ }
constexpr virtual void AddReference() override { /* ... */ }
constexpr virtual void Release() override { /* ... */ }
constexpr SharedPointer GetShared() { return SharedPointer(this, false); }
};
template
class ObjectFactory;
template
class EmplacedRef : public SharedPointer {
template friend class ObjectFactory;
private:
constexpr explicit EmplacedRef(Interface *ptr, bool incref) : SharedPointer(ptr, incref) { /* ... */ }
public:
constexpr EmplacedRef() { /* ... */ }
constexpr Impl &GetImpl() const {
return *impl::EmplacedImplHolder::template GetEmplacedImplPointerImpl(*this);
}
};
template requires (!IsStatefulPolicy)
class ObjectFactory {
private:
template
static constexpr SharedPointer CreateSharedForPointer(T t) {
using Base = impl::ImplTemplateBase;
return SharedPointer(ObjectImplFactory::Create(std::forward(t)), false);
}
public:
template
static constexpr EmplacedRef CreateSharedEmplaced(Args &&... args) {
using Base = impl::ImplTemplateBase, impl::EmplacedImplHolder>;
return EmplacedRef(ObjectImplFactory::Create(std::forward(args)...), false);
}
template
static constexpr SharedPointer CreateUserSharedObject(Args &&... args) {
return SharedPointer(ObjectImplFactory::Create(std::forward(args)...), false);
}
template
static constexpr Impl *GetEmplacedImplPointer(const SharedPointer &sp) {
return impl::EmplacedImplHolder::template GetEmplacedImplPointerImpl(sp);
}
template
static constexpr SharedPointer CreateShared(Smart &&sp) {
return CreateSharedForPointer::type>>(std::forward(sp));
}
template
static constexpr SharedPointer CreateShared(T *p) {
return CreateSharedForPointer>(p);
}
template
static constexpr SharedPointer CreateSharedWithoutManagement(T *p) {
return CreateSharedForPointer>(p);
}
};
template requires (IsStatefulPolicy)
class ObjectFactory {
public:
using Allocator = typename Policy::Allocator;
private:
template
static constexpr SharedPointer CreateSharedForPointer(Allocator *a, T t) {
using Base = impl::ImplTemplateBase;
return SharedPointer(ObjectImplFactory::Create(a, std::forward(t)), false);
}
public:
template
static constexpr EmplacedRef CreateSharedEmplaced(Allocator *a, Args &&... args) {
using Base = impl::ImplTemplateBase, impl::EmplacedImplHolder>;
return EmplacedRef(ObjectImplFactory::Create(a, std::forward(args)...), false);
}
template
static constexpr SharedPointer CreateUserSharedObject(Allocator *a, Args &&... args) {
return SharedPointer(ObjectImplFactory::Create(a, std::forward(args)...), false);
}
template
static constexpr Impl *GetEmplacedImplPointer(const SharedPointer &sp) {
return impl::EmplacedImplHolder::template GetEmplacedImplPointerImpl(sp);
}
template
static constexpr SharedPointer CreateShared(Allocator *a, Smart &&sp) {
return CreateSharedForPointer::type>>(a, std::forward(sp));
}
template
static constexpr SharedPointer CreateShared(Allocator *a, T *p) {
return CreateSharedForPointer>(a, p);
}
template
static constexpr SharedPointer CreateSharedWithoutManagement(Allocator *a, T *p) {
return CreateSharedForPointer>(a, p);
}
};
template
class StatefulObjectFactory {
public:
using Allocator = typename Policy::Allocator;
private:
using StaticObjectFactory = ObjectFactory;
private:
Allocator *m_allocator;
public:
constexpr explicit StatefulObjectFactory(Allocator *a) : m_allocator(a) { /* ... */ }
template
constexpr EmplacedRef CreateSharedEmplaced(Args &&... args) {
return StaticObjectFactory::template CreateSharedEmplaced(m_allocator, std::forward(args)...);
}
template
static constexpr Impl *GetEmplacedImplPointer(const SharedPointer &sp) {
return StaticObjectFactory::template GetEmplacedImplPointer(sp);
}
template
constexpr SharedPointer CreateShared(Allocator *a, Smart &&sp) {
return StaticObjectFactory::template CreateShared(m_allocator, std::forward(sp));
}
template
constexpr SharedPointer CreateShared(Allocator *a, T *p) {
return StaticObjectFactory::template CreateShared(m_allocator, p);
}
template
constexpr SharedPointer CreateSharedWithoutManagement(Allocator *a, T *p) {
return StaticObjectFactory::template CreateSharedWithoutManagement(m_allocator, p);
}
};
using DefaultObjectFactory = ObjectFactory;
using MemoryResourceObjectFactory = ObjectFactory;
template
inline EmplacedRef CreateSharedObjectEmplaced(Args &&... args) {
return DefaultObjectFactory::CreateSharedEmplaced(std::forward(args)...);
}
template
inline EmplacedRef CreateSharedObjectEmplaced(MemoryResource *mr, Args &&... args) {
return MemoryResourceObjectFactory::CreateSharedEmplaced(mr, std::forward(args)...);
}
template
inline SharedPointer CreateSharedObject(Smart &&sp) {
return DefaultObjectFactory::CreateShared(std::forward(sp));
}
template
inline SharedPointer CreateSharedObject(MemoryResource *mr, Smart &&sp) {
return MemoryResourceObjectFactory::CreateShared(mr, std::forward(sp));
}
template
inline SharedPointer CreateSharedObject(T *ptr) {
return DefaultObjectFactory::CreateShared(std::move(ptr));
}
template
inline SharedPointer CreateSharedObjectWithoutManagement(T *ptr) {
return DefaultObjectFactory::CreateSharedWithoutManagement(std::move(ptr));
}
template
inline SharedPointer CreateSharedObjectWithoutManagement(MemoryResource *mr, T *ptr) {
return DefaultObjectFactory::CreateSharedWithoutManagement(mr, std::move(ptr));
}
}