2020-01-30 06:06:25 +00:00
|
|
|
/*
|
|
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
#pragma once
|
2020-01-30 23:29:51 +00:00
|
|
|
#include <mesosphere/kern_common.hpp>
|
2020-01-30 06:06:25 +00:00
|
|
|
#include <mesosphere/kern_k_typed_address.hpp>
|
|
|
|
|
|
|
|
namespace ams::kern {
|
|
|
|
|
|
|
|
class KAutoObject;
|
|
|
|
|
|
|
|
class KClassTokenGenerator {
|
|
|
|
public:
|
|
|
|
using TokenBaseType = u16;
|
|
|
|
public:
|
|
|
|
static constexpr size_t BaseClassBits = 8;
|
|
|
|
static constexpr size_t FinalClassBits = (sizeof(TokenBaseType) * CHAR_BIT) - BaseClassBits;
|
|
|
|
/* One bit per base class. */
|
|
|
|
static constexpr size_t NumBaseClasses = BaseClassBits;
|
|
|
|
/* Final classes are permutations of three bits. */
|
|
|
|
static constexpr size_t NumFinalClasses = [] {
|
|
|
|
TokenBaseType index = 0;
|
|
|
|
for (size_t i = 0; i < FinalClassBits; i++) {
|
|
|
|
for (size_t j = i + 1; j < FinalClassBits; j++) {
|
|
|
|
for (size_t k = j + 1; k < FinalClassBits; k++) {
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return index;
|
|
|
|
}();
|
|
|
|
private:
|
|
|
|
template<TokenBaseType Index>
|
|
|
|
static constexpr inline TokenBaseType BaseClassToken = BIT(Index);
|
|
|
|
|
|
|
|
template<TokenBaseType Index>
|
|
|
|
static constexpr inline TokenBaseType FinalClassToken = [] {
|
|
|
|
TokenBaseType index = 0;
|
|
|
|
for (size_t i = 0; i < FinalClassBits; i++) {
|
|
|
|
for (size_t j = i + 1; j < FinalClassBits; j++) {
|
|
|
|
for (size_t k = j + 1; k < FinalClassBits; k++) {
|
|
|
|
if ((index++) == Index) {
|
|
|
|
return ((1ul << i) | (1ul << j) | (1ul << k)) << BaseClassBits;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
__builtin_unreachable();
|
|
|
|
}();
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
static constexpr inline TokenBaseType GetClassToken() {
|
|
|
|
static_assert(std::is_base_of<KAutoObject, T>::value);
|
|
|
|
if constexpr (std::is_same<T, KAutoObject>::value) {
|
2020-02-22 10:53:14 +00:00
|
|
|
static_assert(T::ObjectType == ObjectType::KAutoObject);
|
|
|
|
return 0;
|
2020-01-30 06:06:25 +00:00
|
|
|
} else if constexpr (!std::is_final<T>::value) {
|
2020-02-22 10:53:14 +00:00
|
|
|
static_assert(ObjectType::BaseClassesStart <= T::ObjectType && T::ObjectType < ObjectType::BaseClassesEnd);
|
2020-01-30 06:06:25 +00:00
|
|
|
constexpr auto ClassIndex = static_cast<TokenBaseType>(T::ObjectType) - static_cast<TokenBaseType>(ObjectType::BaseClassesStart);
|
|
|
|
return BaseClassToken<ClassIndex> | GetClassToken<typename T::BaseClass>();
|
|
|
|
} else if constexpr (ObjectType::FinalClassesStart <= T::ObjectType && T::ObjectType < ObjectType::FinalClassesEnd) {
|
|
|
|
constexpr auto ClassIndex = static_cast<TokenBaseType>(T::ObjectType) - static_cast<TokenBaseType>(ObjectType::FinalClassesStart);
|
|
|
|
return FinalClassToken<ClassIndex> | GetClassToken<typename T::BaseClass>();
|
|
|
|
} else {
|
|
|
|
static_assert(!std::is_same<T, T>::value, "GetClassToken: Invalid Type");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
public:
|
|
|
|
enum class ObjectType {
|
2020-02-22 10:53:14 +00:00
|
|
|
KAutoObject,
|
2020-01-30 06:06:25 +00:00
|
|
|
|
2020-02-22 10:53:14 +00:00
|
|
|
BaseClassesStart,
|
|
|
|
|
|
|
|
KSynchronizationObject = BaseClassesStart,
|
2020-01-30 06:06:25 +00:00
|
|
|
KReadableEvent,
|
|
|
|
|
|
|
|
BaseClassesEnd,
|
|
|
|
|
|
|
|
FinalClassesStart = BaseClassesEnd,
|
|
|
|
|
|
|
|
KInterruptEvent = FinalClassesStart,
|
|
|
|
KDebug,
|
|
|
|
KThread,
|
|
|
|
KServerPort,
|
|
|
|
KServerSession,
|
|
|
|
KClientPort,
|
|
|
|
KClientSession,
|
|
|
|
KProcess,
|
|
|
|
KResourceLimit,
|
|
|
|
KLightSession,
|
|
|
|
KPort,
|
|
|
|
KSession,
|
|
|
|
KSharedMemory,
|
|
|
|
KEvent,
|
|
|
|
KWritableEvent,
|
|
|
|
KLightClientSession,
|
|
|
|
KLightServerSession,
|
|
|
|
KTransferMemory,
|
|
|
|
KDeviceAddressSpace,
|
|
|
|
KSessionRequest,
|
|
|
|
KCodeMemory,
|
|
|
|
|
|
|
|
FinalClassesEnd = FinalClassesStart + NumFinalClasses,
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
static constexpr inline TokenBaseType ClassToken = GetClassToken<T>();
|
|
|
|
};
|
|
|
|
|
|
|
|
using ClassTokenType = KClassTokenGenerator::TokenBaseType;
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
static constexpr inline ClassTokenType ClassToken = KClassTokenGenerator::ClassToken<T>;
|
|
|
|
|
|
|
|
}
|