/* * 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 "sf_common.hpp" #include "sf_out.hpp" #include "cmif/sf_cmif_pointer_and_size.hpp" 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; 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->(); } }; using OutMoveHandle = sf::Out; using OutCopyHandle = sf::Out; }