/*
* Copyright (c) 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
namespace ams::sf {
namespace impl {
struct InHandleTag{};
struct OutHandleTag{};
template
struct InHandle : public InHandleTag {
::Handle handle;
constexpr InHandle() : handle(INVALID_HANDLE) { /* ... */ }
constexpr InHandle(::Handle h) : handle(h) { /* ... */ }
constexpr InHandle(const InHandle &o) : handle(o.handle) { /* ... */ }
constexpr void operator=(const ::Handle &h) { this->handle = h; }
constexpr void operator=(const InHandle &o) { this->handle = o.handle; }
constexpr /* TODO: explicit? */ operator ::Handle() const { return this->handle; }
constexpr ::Handle GetValue() const { return this->handle; }
};
template
class OutHandleImpl : public OutHandleTag {
static_assert(std::is_base_of::value, "OutHandleImpl requires InHandle base");
private:
T *ptr;
public:
constexpr OutHandleImpl(T *p) : ptr(p) { /* ... */ }
constexpr void SetValue(const Handle &value) {
*this->ptr = value;
}
constexpr void SetValue(const T &value) {
*this->ptr = value;
}
constexpr const T &GetValue() const {
return *this->ptr;
}
constexpr T *GetPointer() const {
return this->ptr;
}
constexpr Handle *GetHandlePointer() const {
return &this->ptr->handle;
}
constexpr T &operator *() const {
return *this->ptr;
}
constexpr T *operator ->() const {
return this->ptr;
}
};
}
using MoveHandle = typename impl::InHandle;
using CopyHandle = typename impl::InHandle;
static_assert(sizeof(MoveHandle) == sizeof(::Handle), "sizeof(MoveHandle)");
static_assert(sizeof(CopyHandle) == sizeof(::Handle), "sizeof(CopyHandle)");
template<>
class IsOutForceEnabled : public std::true_type{};
template<>
class IsOutForceEnabled : public std::true_type{};
template<>
class Out : public impl::OutHandleImpl {
private:
using T = MoveHandle;
using Base = impl::OutHandleImpl;
public:
constexpr Out(T *p) : Base(p) { /* ... */ }
constexpr void SetValue(const Handle &value) {
Base::SetValue(value);
}
constexpr void SetValue(const T &value) {
Base::SetValue(value);
}
constexpr const T &GetValue() const {
return Base::GetValue();
}
constexpr T *GetPointer() const {
return Base::GetPointer();
}
constexpr Handle *GetHandlePointer() const {
return Base::GetHandlePointer();
}
constexpr T &operator *() const {
return Base::operator*();
}
constexpr T *operator ->() const {
return Base::operator->();
}
};
template<>
class Out : public impl::OutHandleImpl {
private:
using T = CopyHandle;
using Base = impl::OutHandleImpl;
private:
bool *m_managed;
public:
constexpr Out(T *p) : Base(p), m_managed(nullptr) { /* ... */ }
constexpr Out(T *p, bool *m) : Base(p), m_managed(m) { /* ... */ }
constexpr void SetValue(const Handle &value) {
Base::SetValue(value);
}
constexpr void SetValue(const T &value) {
Base::SetValue(value);
}
constexpr void SetManaged(bool m) {
AMS_ASSERT(m_managed != nullptr);
*m_managed = m;
}
constexpr const T &GetValue() const {
return Base::GetValue();
}
constexpr T *GetPointer() const {
return Base::GetPointer();
}
constexpr Handle *GetHandlePointer() const {
return Base::GetHandlePointer();
}
constexpr T &operator *() const {
return Base::operator*();
}
constexpr T *operator ->() const {
return Base::operator->();
}
};
using OutMoveHandle = sf::Out;
using OutCopyHandle = sf::Out;
}