ams: support building unit test programs on windows/linux/macos

This commit is contained in:
Michael Scire
2022-03-06 12:08:20 -08:00
committed by SciresM
parent 9a38be201a
commit 64a97576d0
756 changed files with 33359 additions and 9372 deletions

View File

@@ -49,6 +49,8 @@ namespace ams {
ALWAYS_INLINE bool IsEqual(const MemoryResource &resource) const {
return this->IsEqualImpl(resource);
}
public:
constexpr ~MemoryResource() = default;
protected:
virtual void *AllocateImpl(size_t size, size_t alignment) = 0;
virtual void DeallocateImpl(void *buffer, size_t size, size_t alignment) = 0;

View File

@@ -18,12 +18,12 @@
namespace ams::diag {
NORETURN NOINLINE void AssertionFailureImpl(const char *file, int line, const char *func, const char *expr, u64 value, const char *format, ...) __attribute__((format(printf, 6, 7)));
NORETURN NOINLINE void AssertionFailureImpl(const char *file, int line, const char *func, const char *expr, u64 value);
NORETURN void AssertionFailureImpl(const char *file, int line, const char *func, const char *expr, u64 value, const char *format, ...) __attribute__((format(printf, 6, 7)));
NORETURN void AssertionFailureImpl(const char *file, int line, const char *func, const char *expr, u64 value);
NORETURN NOINLINE void AbortImpl(const char *file, int line, const char *func, const char *expr, u64 value, const char *format, ...) __attribute__((format(printf, 6, 7)));
NORETURN NOINLINE void AbortImpl(const char *file, int line, const char *func, const char *expr, u64 value);
NORETURN NOINLINE void AbortImpl();
NORETURN void AbortImpl(const char *file, int line, const char *func, const char *expr, u64 value, const char *format, ...) __attribute__((format(printf, 6, 7)));
NORETURN void AbortImpl(const char *file, int line, const char *func, const char *expr, u64 value);
NORETURN void AbortImpl();
}
@@ -36,12 +36,16 @@ namespace ams::diag {
#endif
#ifdef AMS_ENABLE_ASSERTIONS
#define AMS_ASSERT_IMPL(expr, ...) \
({ \
if (const bool __tmp_ams_assert_val = static_cast<bool>(expr); AMS_UNLIKELY(!__tmp_ams_assert_val)) { \
AMS_CALL_ASSERT_FAIL_IMPL(#expr, ## __VA_ARGS__); \
} \
})
#define AMS_ASSERT_IMPL(expr, ...) \
{ \
if (std::is_constant_evaluated()) { \
AMS_ASSUME(static_cast<bool>(expr)); \
} else { \
if (const bool __tmp_ams_assert_val = static_cast<bool>(expr); (!__tmp_ams_assert_val)) { \
AMS_CALL_ASSERT_FAIL_IMPL(#expr, ## __VA_ARGS__); \
} \
} \
}
#elif defined(AMS_PRESERVE_ASSERTION_EXPRESSIONS)
#define AMS_ASSERT_IMPL(expr, ...) AMS_UNUSED(expr, ## __VA_ARGS__)
#else
@@ -62,9 +66,13 @@ namespace ams::diag {
#define AMS_ABORT(...) AMS_CALL_ABORT_IMPL("", ## __VA_ARGS__)
#define AMS_ABORT_UNLESS(expr, ...) \
({ \
if (const bool __tmp_ams_assert_val = static_cast<bool>(expr); AMS_UNLIKELY(!__tmp_ams_assert_val)) { \
AMS_CALL_ABORT_IMPL(#expr, ##__VA_ARGS__); \
} \
})
#define AMS_ABORT_UNLESS(expr, ...) \
{ \
if (std::is_constant_evaluated()) { \
AMS_ASSUME(static_cast<bool>(expr)); \
} else { \
if (const bool __tmp_ams_assert_val = static_cast<bool>(expr); AMS_UNLIKELY(!__tmp_ams_assert_val)) { \
AMS_CALL_ABORT_IMPL(#expr, ##__VA_ARGS__); \
} \
} \
}

View File

@@ -16,6 +16,7 @@
#pragma once
#include <vapours/includes.hpp>
#include <vapours/defines.hpp>
#include <vapours/compiler.hpp>
#if defined(AMS_FORCE_DISABLE_DETAILED_ASSERTIONS) && defined(AMS_FORCE_ENABLE_DETAILED_ASSERTIONS)
#error "Invalid detailed assertions state"

View File

@@ -0,0 +1,24 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours/includes.hpp>
#include <vapours/defines.hpp>
#if defined(ATMOSPHERE_COMPILER_CLANG)
#include <vapours/impl/compiler_impl.clang.hpp>
#elif defined(ATMOSPHERE_COMPILER_GCC)
#include <vapours/impl/compiler_impl.gcc.hpp>
#endif

View File

@@ -22,6 +22,7 @@
#include <vapours/crypto/crypto_md5_generator.hpp>
#include <vapours/crypto/crypto_sha1_generator.hpp>
#include <vapours/crypto/crypto_sha256_generator.hpp>
#include <vapours/crypto/crypto_sha3_generator.hpp>
#include <vapours/crypto/crypto_aes_encryptor.hpp>
#include <vapours/crypto/crypto_aes_decryptor.hpp>
#include <vapours/crypto/crypto_aes_ctr_encryptor_decryptor.hpp>

View File

@@ -22,6 +22,10 @@ namespace ams::crypto {
using HmacSha1Generator = HmacGenerator<Sha1Generator>;
void GenerateHmacSha1Mac(void *dst, size_t dst_size, const void *data, size_t data_size, const void *key, size_t key_size);
void GenerateHmacSha1(void *dst, size_t dst_size, const void *data, size_t data_size, const void *key, size_t key_size);
ALWAYS_INLINE void GenerateHmacSha1Mac(void *dst, size_t dst_size, const void *data, size_t data_size, const void *key, size_t key_size) {
return GenerateHmacSha1(dst, dst_size, data, data_size, key, key_size);
}
}

View File

@@ -22,6 +22,10 @@ namespace ams::crypto {
using HmacSha256Generator = HmacGenerator<Sha256Generator>;
void GenerateHmacSha256Mac(void *dst, size_t dst_size, const void *data, size_t data_size, const void *key, size_t key_size);
void GenerateHmacSha256(void *dst, size_t dst_size, const void *data, size_t data_size, const void *key, size_t key_size);
ALWAYS_INLINE void GenerateHmacSha256Mac(void *dst, size_t dst_size, const void *data, size_t data_size, const void *key, size_t key_size) {
return GenerateHmacSha256(dst, dst_size, data, data_size, key, key_size);
}
}

View File

@@ -58,6 +58,10 @@ namespace ams::crypto {
}
};
void GenerateMd5Hash(void *dst, size_t dst_size, const void *src, size_t src_size);
void GenerateMd5(void *dst, size_t dst_size, const void *src, size_t src_size);
ALWAYS_INLINE void GenerateMd5Hash(void *dst, size_t dst_size, const void *src, size_t src_size) {
return GenerateMd5(dst, dst_size, src, src_size);
}
}

View File

@@ -58,6 +58,10 @@ namespace ams::crypto {
}
};
void GenerateSha1Hash(void *dst, size_t dst_size, const void *src, size_t src_size);
void GenerateSha1(void *dst, size_t dst_size, const void *src, size_t src_size);
ALWAYS_INLINE void GenerateSha1Hash(void *dst, size_t dst_size, const void *src, size_t src_size) {
return GenerateSha1(dst, dst_size, src, src_size);
}
}

View File

@@ -79,6 +79,10 @@ namespace ams::crypto {
}
};
void GenerateSha256Hash(void *dst, size_t dst_size, const void *src, size_t src_size);
void GenerateSha256(void *dst, size_t dst_size, const void *src, size_t src_size);
ALWAYS_INLINE void GenerateSha256Hash(void *dst, size_t dst_size, const void *src, size_t src_size) {
return GenerateSha256(dst, dst_size, src, src_size);
}
}

View File

@@ -0,0 +1,125 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours/common.hpp>
#include <vapours/assert.hpp>
#include <vapours/util.hpp>
#include <vapours/crypto/impl/crypto_sha3_impl.hpp>
namespace ams::crypto {
struct Sha3Context {
u32 hash_size;
u32 buffered_bytes;
u64 internal_state[25];
};
namespace impl {
template<size_t HashSize>
struct Sha3Asn1IdentifierByte;
template<> struct Sha3Asn1IdentifierByte<224 / BITSIZEOF(u8)> { static constexpr u8 Value = 0x07; };
template<> struct Sha3Asn1IdentifierByte<256 / BITSIZEOF(u8)> { static constexpr u8 Value = 0x08; };
template<> struct Sha3Asn1IdentifierByte<384 / BITSIZEOF(u8)> { static constexpr u8 Value = 0x09; };
template<> struct Sha3Asn1IdentifierByte<512 / BITSIZEOF(u8)> { static constexpr u8 Value = 0x0A; };
}
template <size_t _HashSize>
class Sha3Generator {
NON_COPYABLE(Sha3Generator);
NON_MOVEABLE(Sha3Generator);
private:
using Impl = impl::Sha3Impl<_HashSize>;
public:
static constexpr size_t HashSize = Impl::HashSize;
static constexpr size_t BlockSize = Impl::BlockSize;
static constexpr inline u8 Asn1Identifier[] = {
0x30, 0x31, /* Sequence, size 0x31 */
0x30, 0x0D, /* Sequence, size 0x0D */
0x06, 0x09, /* Object Identifier */
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, impl::Sha3Asn1IdentifierByte<HashSize>::Value, /* SHA3-*** */
0x05, 0x00, /* Null */
0x04, 0x20, /* Octet string, size 0x20 */
};
static constexpr size_t Asn1IdentifierSize = util::size(Asn1Identifier);
private:
Impl m_impl;
public:
Sha3Generator() { /* ... */ }
void Initialize() {
m_impl.Initialize();
}
void Update(const void *data, size_t size) {
m_impl.Update(data, size);
}
void GetHash(void *dst, size_t size) {
m_impl.GetHash(dst, size);
}
void InitializeWithContext(const Sha3Context *context) {
m_impl.InitializeWithContext(context);
}
void GetContext(Sha3Context *context) const {
m_impl.GetContext(context);
}
};
using Sha3224Generator = Sha3Generator<224 / BITSIZEOF(u8)>;
using Sha3256Generator = Sha3Generator<256 / BITSIZEOF(u8)>;
using Sha3384Generator = Sha3Generator<384 / BITSIZEOF(u8)>;
using Sha3512Generator = Sha3Generator<512 / BITSIZEOF(u8)>;
inline void GenerateSha3224(void *dst, size_t dst_size, const void *src, size_t src_size) {
Sha3224Generator generator;
generator.Initialize();
generator.Update(src, src_size);
generator.GetHash(dst, dst_size);
}
inline void GenerateSha3256(void *dst, size_t dst_size, const void *src, size_t src_size) {
Sha3256Generator generator;
generator.Initialize();
generator.Update(src, src_size);
generator.GetHash(dst, dst_size);
}
inline void GenerateSha3384(void *dst, size_t dst_size, const void *src, size_t src_size) {
Sha3384Generator generator;
generator.Initialize();
generator.Update(src, src_size);
generator.GetHash(dst, dst_size);
}
inline void GenerateSha3512(void *dst, size_t dst_size, const void *src, size_t src_size) {
Sha3512Generator generator;
generator.Initialize();
generator.Update(src, src_size);
generator.GetHash(dst, dst_size);
}
}

View File

@@ -174,7 +174,11 @@ namespace ams::crypto::impl {
}
template<> void CtrModeImpl<AesEncryptor128>::ProcessBlocks(u8 *dst, const u8 *src, size_t num_blocks);
/* TODO: Optimized x64 CTR-192/256? */
#if defined(ATMOSPHERE_ARCH_ARM64)
template<> void CtrModeImpl<AesEncryptor192>::ProcessBlocks(u8 *dst, const u8 *src, size_t num_blocks);
template<> void CtrModeImpl<AesEncryptor256>::ProcessBlocks(u8 *dst, const u8 *src, size_t num_blocks);
#endif
}

View File

@@ -29,25 +29,30 @@ namespace ams::crypto::impl {
static constexpr size_t HashSize = 0x14;
static constexpr size_t BlockSize = 0x40;
private:
struct State {
u32 intermediate_hash[HashSize / sizeof(u32)];
u8 buffer[BlockSize];
u64 bits_consumed;
size_t num_buffered;
bool finalized;
enum State {
State_None,
State_Initialized,
State_Done,
};
private:
u32 m_intermediate_hash[HashSize / sizeof(u32)];
u8 m_buffer[BlockSize];
size_t m_buffered_bytes;
u64 m_bits_consumed;
State m_state;
public:
Sha1Impl() { m_state.finalized = false; }
Sha1Impl() : m_state(State_None) { /* ... */ }
~Sha1Impl() {
static_assert(std::is_trivially_destructible<State>::value);
ClearMemory(std::addressof(m_state), sizeof(m_state));
ClearMemory(this, sizeof(*this));
}
void Initialize();
void Update(const void *data, size_t size);
void GetHash(void *dst, size_t size);
private:
void ProcessBlock(const void *data);
void ProcessBlocks(const u8 *data, size_t block_count);
void ProcessLastBlock();
};
/* static_assert(HashFunction<Sha1Impl>); */

View File

@@ -34,20 +34,21 @@ namespace ams::crypto::impl {
static constexpr size_t HashSize = 0x20;
static constexpr size_t BlockSize = 0x40;
private:
struct State {
u32 intermediate_hash[HashSize / sizeof(u32)];
u8 buffer[BlockSize];
u64 bits_consumed;
size_t num_buffered;
bool finalized;
enum State {
State_None,
State_Initialized,
State_Done,
};
private:
u32 m_intermediate_hash[HashSize / sizeof(u32)];
u8 m_buffer[BlockSize];
size_t m_buffered_bytes;
u64 m_bits_consumed;
State m_state;
public:
Sha256Impl() { m_state.finalized = false; }
Sha256Impl() : m_state(State_None) { /* ... */ }
~Sha256Impl() {
static_assert(std::is_trivially_destructible<State>::value);
ClearMemory(std::addressof(m_state), sizeof(m_state));
ClearMemory(this, sizeof(*this));
}
void Initialize();
@@ -57,14 +58,18 @@ namespace ams::crypto::impl {
void InitializeWithContext(const Sha256Context *context);
size_t GetContext(Sha256Context *context) const;
size_t GetBufferedDataSize() const { return m_state.num_buffered; }
size_t GetBufferedDataSize() const { return m_buffered_bytes; }
void GetBufferedData(void *dst, size_t dst_size) const {
AMS_ASSERT(dst_size >= this->GetBufferedDataSize());
AMS_UNUSED(dst_size);
std::memcpy(dst, m_state.buffer, this->GetBufferedDataSize());
std::memcpy(dst, m_buffer, m_buffered_bytes);
}
private:
void ProcessBlock(const void *data);
void ProcessBlocks(const u8 *data, size_t block_count);
void ProcessLastBlock();
};
static_assert(HashFunction<Sha256Impl>);

View File

@@ -0,0 +1,70 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours/common.hpp>
#include <vapours/assert.hpp>
#include <vapours/util.hpp>
#include <vapours/crypto/impl/crypto_hash_function.hpp>
#include <vapours/crypto/crypto_memory_clear.hpp>
namespace ams::crypto {
struct Sha3Context;
}
namespace ams::crypto::impl {
template<size_t _HashSize>
class Sha3Impl {
public:
static constexpr size_t InternalStateSize = 200;
static constexpr size_t HashSize = _HashSize;
static constexpr size_t BlockSize = InternalStateSize - 2 * HashSize;
private:
enum State {
State_None,
State_Initialized,
State_Done,
};
private:
u64 m_internal_state[InternalStateSize / sizeof(u64)];
size_t m_buffered_bytes;
State m_state;
public:
Sha3Impl() : m_state(State_None) { /* ... */ }
~Sha3Impl() {
ClearMemory(this, sizeof(*this));
}
void Initialize();
void Update(const void *data, size_t size);
void GetHash(void *dst, size_t size);
void InitializeWithContext(const Sha3Context *context);
void GetContext(Sha3Context *context) const;
private:
void ProcessBlock();
void ProcessLastBlock();
};
static_assert(HashFunction<Sha3Impl<224 / BITSIZEOF(u8)>>);
static_assert(HashFunction<Sha3Impl<256 / BITSIZEOF(u8)>>);
static_assert(HashFunction<Sha3Impl<384 / BITSIZEOF(u8)>>);
static_assert(HashFunction<Sha3Impl<512 / BITSIZEOF(u8)>>);
}

View File

@@ -125,6 +125,7 @@ namespace ams::crypto::impl {
size_t ProcessRemainingData(u8 *dst, const u8 *src, size_t size);
};
#if defined(ATMOSPHERE_ARCH_ARM64)
template<> size_t XtsModeImpl::Update<AesEncryptor128>(void *dst, size_t dst_size, const void *src, size_t src_size);
template<> size_t XtsModeImpl::Update<AesEncryptor192>(void *dst, size_t dst_size, const void *src, size_t src_size);
template<> size_t XtsModeImpl::Update<AesEncryptor256>(void *dst, size_t dst_size, const void *src, size_t src_size);
@@ -132,5 +133,6 @@ namespace ams::crypto::impl {
template<> size_t XtsModeImpl::Update<AesDecryptor128>(void *dst, size_t dst_size, const void *src, size_t src_size);
template<> size_t XtsModeImpl::Update<AesDecryptor192>(void *dst, size_t dst_size, const void *src, size_t src_size);
template<> size_t XtsModeImpl::Update<AesDecryptor256>(void *dst, size_t dst_size, const void *src, size_t src_size);
#endif
}

View File

@@ -24,6 +24,8 @@ namespace ams::dd {
using PhysicalAddress = u64;
using DeviceVirtualAddress = u64;
#if defined(ATMOSPHERE_OS_HORIZON)
static_assert(std::same_as<PhysicalAddress, ams::svc::PhysicalAddress>);
#endif
}

View File

@@ -18,6 +18,34 @@
/* Any broadly useful language defines should go here. */
#if defined(ATMOSPHERE_OS_WINDOWS)
#if defined(ATMOSPHERE_ARCH_ARM64) || defined(ATMOSPHERE_ARCH_X64)
static_assert(sizeof(size_t) == sizeof(uint64_t));
#define PRIuZ PRIu64
#define PRIxZ PRIx64
#define PRIXZ PRIX64
#elif defined(ATMOSPHERE_ARCH_ARM) || defined(ATMOSPHERE_ARCH_X86)
static_assert(sizeof(size_t) == sizeof(uint32_t));
#define PRIuZ PRIu32
#define PRIxZ PRIx32
#define PRIXZ PRIX32
#endif
#else
#define PRIuZ "zu"
#define PRIxZ "zx"
#define PRIXZ "zX"
#endif
#if defined(__clang__)
#define ATMOSPHERE_COMPILER_CLANG
#elif defined(__GNUG__) || defined(__GNUC__)
#define ATMOSPHERE_COMPILER_GCC
#else
#error "Unknown compiler!"
#endif
#define NON_COPYABLE(cls) \
cls(const cls&) = delete; \
cls& operator=(const cls&) = delete
@@ -41,6 +69,10 @@
#define STRINGIZE(x) STRINGIZE_IMPL(x)
#define STRINGIZE_IMPL(x) #x
#ifndef PACKED
#define PACKED __attribute__((packed))
#endif
#ifdef __COUNTER__
#define ANONYMOUS_VARIABLE(pref) CONCATENATE(pref, __COUNTER__)
#else

View File

@@ -30,8 +30,7 @@
#include <vapours/assert.hpp>
#include <vapours/util/util_type_traits.hpp>
#pragma GCC push_options
#pragma GCC optimize ("-O3")
AMS_PRAGMA_BEGIN_OPTIMIZE_O3()
/*
* This file defines data structures for red-black trees.
@@ -626,4 +625,4 @@ namespace ams::freebsd {
}
#pragma GCC pop_options
AMS_PRAGMA_END_OPTIMIZE()

View File

@@ -0,0 +1,24 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours/includes.hpp>
#include <vapours/defines.hpp>
#define AMS_PRAGMA_BEGIN_OPTIMIZE_O3()
#define AMS_PRAGMA_BEGIN_OPTIMIZE_OS()
#define AMS_PRAGMA_END_OPTIMIZE()
#define AMS_CONCEPTS_REQUIRES_IF_SUPPORTED(__EXPR__)

View File

@@ -0,0 +1,31 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours/includes.hpp>
#include <vapours/defines.hpp>
#define AMS_PRAGMA_BEGIN_OPTIMIZE_O3() \
_Pragma("GCC push_options") \
_Pragma("GCC optimize (\"-O3\")")
#define AMS_PRAGMA_BEGIN_OPTIMIZE_OS() \
_Pragma("GCC push_options") \
_Pragma("GCC optimize (\"-Os\")")
#define AMS_PRAGMA_END_OPTIMIZE() \
_Pragma("GCC pop_options")
#define AMS_CONCEPTS_REQUIRES_IF_SUPPORTED(__EXPR__) requires (__EXPR__)

View File

@@ -16,6 +16,9 @@
#pragma once
/* Unconditionally include type-traits as first header. */
#include <type_traits>
/* C headers. */
#include <cstdint>
#include <cstdarg>
@@ -28,7 +31,6 @@
#include <cinttypes>
/* C++ headers. */
#include <type_traits>
#include <concepts>
#include <algorithm>
#include <iterator>
@@ -52,11 +54,20 @@
#include <unordered_map>
#include <set>
#if defined(ATMOSPHERE_OS_HORIZON) && defined(ATMOSPHERE_BOARD_NINTENDO_NX)
/* Libnx. */
#include <switch.h>
#else
/* Non-switch code can't include libnx. */
#include "types.hpp"
#endif
#else
/* Non-EL0 code can't include libnx. */
#include "types.hpp"

View File

@@ -56,68 +56,76 @@ namespace ams::fs {
R_DEFINE_ERROR_RESULT(SystemPartitionNotReady, 3100);
R_DEFINE_ERROR_RANGE(AllocationFailure, 3200, 3499);
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemAccessorA, 3211);
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemAccessorB, 3212);
R_DEFINE_ERROR_RESULT(AllocationFailureInApplicationA, 3213);
R_DEFINE_ERROR_RESULT(AllocationFailureInBisA, 3215);
R_DEFINE_ERROR_RESULT(AllocationFailureInBisB, 3216);
R_DEFINE_ERROR_RESULT(AllocationFailureInBisC, 3217);
R_DEFINE_ERROR_RESULT(AllocationFailureInCodeA, 3218);
R_DEFINE_ERROR_RESULT(AllocationFailureInContentA, 3219);
R_DEFINE_ERROR_RESULT(AllocationFailureInContentStorageA, 3220);
R_DEFINE_ERROR_RESULT(AllocationFailureInContentStorageB, 3221);
R_DEFINE_ERROR_RESULT(AllocationFailureInDataA, 3222);
R_DEFINE_ERROR_RESULT(AllocationFailureInDataB, 3223);
R_DEFINE_ERROR_RESULT(AllocationFailureInDeviceSaveDataA, 3224);
R_DEFINE_ERROR_RESULT(AllocationFailureInGameCardA, 3225);
R_DEFINE_ERROR_RESULT(AllocationFailureInGameCardB, 3226);
R_DEFINE_ERROR_RESULT(AllocationFailureInGameCardC, 3227);
R_DEFINE_ERROR_RESULT(AllocationFailureInGameCardD, 3228);
R_DEFINE_ERROR_RESULT(AllocationFailureInImageDirectoryA, 3232);
R_DEFINE_ERROR_RESULT(AllocationFailureInSdCardA, 3244);
R_DEFINE_ERROR_RESULT(AllocationFailureInSdCardB, 3245);
R_DEFINE_ERROR_RESULT(AllocationFailureInSystemSaveDataA, 3246);
R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemA, 3247);
R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemB, 3248);
R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemC, 3249);
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemProxyCoreImplD, 3256);
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemProxyCoreImplE, 3257);
R_DEFINE_ERROR_RESULT(AllocationFailureInProgramRegistryManagerA, 3258);
R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemCreatorA, 3280);
R_DEFINE_ERROR_RESULT(AllocationFailureInRomFileSystemCreatorA, 3281);
R_DEFINE_ERROR_RESULT(AllocationFailureInStorageOnNcaCreatorA, 3288);
R_DEFINE_ERROR_RESULT(AllocationFailureInStorageOnNcaCreatorB, 3289);
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemBuddyHeapA, 3294);
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemBufferManagerA, 3295);
R_DEFINE_ERROR_RESULT(AllocationFailureInBlockCacheBufferedStorageA, 3296);
R_DEFINE_ERROR_RESULT(AllocationFailureInBlockCacheBufferedStorageB, 3297);
R_DEFINE_ERROR_RESULT(AllocationFailureInIntegrityVerificationStorageA, 3304);
R_DEFINE_ERROR_RESULT(AllocationFailureInIntegrityVerificationStorageB, 3305);
R_DEFINE_ERROR_RESULT(AllocationFailureInDirectorySaveDataFileSystem, 3321);
R_DEFINE_ERROR_RESULT(AllocationFailureInNcaFileSystemDriverI, 3341);
R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemA, 3347);
R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemB, 3348);
R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemC, 3349);
R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemMetaA, 3350);
R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemMetaB, 3351);
R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemD, 3352);
R_DEFINE_ERROR_RESULT(AllocationFailureInSubDirectoryFileSystem, 3355);
R_DEFINE_ERROR_RESULT(AllocationFailureInNcaReaderA, 3363);
R_DEFINE_ERROR_RESULT(AllocationFailureInRegisterA, 3365);
R_DEFINE_ERROR_RESULT(AllocationFailureInRegisterB, 3366);
R_DEFINE_ERROR_RESULT(AllocationFailureInPathNormalizer, 3367);
R_DEFINE_ERROR_RESULT(AllocationFailureInDbmRomKeyValueStorage, 3375);
R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemE, 3377);
R_DEFINE_ERROR_RESULT(AllocationFailureInReadOnlyFileSystemA, 3386);
R_DEFINE_ERROR_RESULT(AllocationFailureInAesCtrCounterExtendedStorageA, 3399);
R_DEFINE_ERROR_RESULT(AllocationFailureInAesCtrCounterExtendedStorageB, 3400);
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemInterfaceAdapter, 3407);
R_DEFINE_ERROR_RESULT(AllocationFailureInBufferedStorageA, 3411);
R_DEFINE_ERROR_RESULT(AllocationFailureInIntegrityRomFsStorageA, 3412);
R_DEFINE_ERROR_RESULT(AllocationFailureInNew, 3420);
R_DEFINE_ERROR_RESULT(AllocationFailureInMakeUnique, 3422);
R_DEFINE_ERROR_RESULT(AllocationFailureInAllocateShared, 3423);
R_DEFINE_ERROR_RESULT(AllocationFailurePooledBufferNotEnoughSize, 3424);
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemAccessorA, 3211);
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemAccessorB, 3212);
R_DEFINE_ERROR_RESULT(AllocationFailureInApplicationA, 3213);
R_DEFINE_ERROR_RESULT(AllocationFailureInBisA, 3215);
R_DEFINE_ERROR_RESULT(AllocationFailureInBisB, 3216);
R_DEFINE_ERROR_RESULT(AllocationFailureInBisC, 3217);
R_DEFINE_ERROR_RESULT(AllocationFailureInCodeA, 3218);
R_DEFINE_ERROR_RESULT(AllocationFailureInContentA, 3219);
R_DEFINE_ERROR_RESULT(AllocationFailureInContentStorageA, 3220);
R_DEFINE_ERROR_RESULT(AllocationFailureInContentStorageB, 3221);
R_DEFINE_ERROR_RESULT(AllocationFailureInDataA, 3222);
R_DEFINE_ERROR_RESULT(AllocationFailureInDataB, 3223);
R_DEFINE_ERROR_RESULT(AllocationFailureInDeviceSaveDataA, 3224);
R_DEFINE_ERROR_RESULT(AllocationFailureInGameCardA, 3225);
R_DEFINE_ERROR_RESULT(AllocationFailureInGameCardB, 3226);
R_DEFINE_ERROR_RESULT(AllocationFailureInGameCardC, 3227);
R_DEFINE_ERROR_RESULT(AllocationFailureInGameCardD, 3228);
R_DEFINE_ERROR_RESULT(AllocationFailureInHostA, 3229);
R_DEFINE_ERROR_RESULT(AllocationFailureInHostB, 3230);
R_DEFINE_ERROR_RESULT(AllocationFailureInHostC, 3231);
R_DEFINE_ERROR_RESULT(AllocationFailureInImageDirectoryA, 3232);
R_DEFINE_ERROR_RESULT(AllocationFailureInSdCardA, 3244);
R_DEFINE_ERROR_RESULT(AllocationFailureInSdCardB, 3245);
R_DEFINE_ERROR_RESULT(AllocationFailureInSystemSaveDataA, 3246);
R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemA, 3247);
R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemB, 3248);
R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemC, 3249);
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemProxyCoreImplD, 3256);
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemProxyCoreImplE, 3257);
R_DEFINE_ERROR_RESULT(AllocationFailureInProgramRegistryManagerA, 3258);
R_DEFINE_ERROR_RESULT(AllocationFailureInLocalFileSystemCreatorA, 3279);
R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemCreatorA, 3280);
R_DEFINE_ERROR_RESULT(AllocationFailureInRomFileSystemCreatorA, 3281);
R_DEFINE_ERROR_RESULT(AllocationFailureInStorageOnNcaCreatorA, 3288);
R_DEFINE_ERROR_RESULT(AllocationFailureInStorageOnNcaCreatorB, 3289);
R_DEFINE_ERROR_RESULT(AllocationFailureInSubDirectoryFileSystemCreatorA, 3290);
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemBuddyHeapA, 3294);
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemBufferManagerA, 3295);
R_DEFINE_ERROR_RESULT(AllocationFailureInBlockCacheBufferedStorageA, 3296);
R_DEFINE_ERROR_RESULT(AllocationFailureInBlockCacheBufferedStorageB, 3297);
R_DEFINE_ERROR_RESULT(AllocationFailureInIntegrityVerificationStorageA, 3304);
R_DEFINE_ERROR_RESULT(AllocationFailureInIntegrityVerificationStorageB, 3305);
R_DEFINE_ERROR_RESULT(AllocationFailureInDirectorySaveDataFileSystem, 3321);
R_DEFINE_ERROR_RESULT(AllocationFailureInLocalFileSystemA, 3322);
R_DEFINE_ERROR_RESULT(AllocationFailureInLocalFileSystemB, 3323);
R_DEFINE_ERROR_RESULT(AllocationFailureInNcaFileSystemDriverI, 3341);
R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemA, 3347);
R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemB, 3348);
R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemC, 3349);
R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemMetaA, 3350);
R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemMetaB, 3351);
R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemD, 3352);
R_DEFINE_ERROR_RESULT(AllocationFailureInSubDirectoryFileSystem, 3355);
R_DEFINE_ERROR_RESULT(AllocationFailureInNcaReaderA, 3363);
R_DEFINE_ERROR_RESULT(AllocationFailureInRegisterA, 3365);
R_DEFINE_ERROR_RESULT(AllocationFailureInRegisterB, 3366);
R_DEFINE_ERROR_RESULT(AllocationFailureInPathNormalizer, 3367);
R_DEFINE_ERROR_RESULT(AllocationFailureInDbmRomKeyValueStorage, 3375);
R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemE, 3377);
R_DEFINE_ERROR_RESULT(AllocationFailureInReadOnlyFileSystemA, 3386);
R_DEFINE_ERROR_RESULT(AllocationFailureInAesCtrCounterExtendedStorageA, 3399);
R_DEFINE_ERROR_RESULT(AllocationFailureInAesCtrCounterExtendedStorageB, 3400);
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemInterfaceAdapter, 3407);
R_DEFINE_ERROR_RESULT(AllocationFailureInBufferedStorageA, 3411);
R_DEFINE_ERROR_RESULT(AllocationFailureInIntegrityRomFsStorageA, 3412);
R_DEFINE_ERROR_RESULT(AllocationFailureInNew, 3420);
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemProxyImplA, 3421);
R_DEFINE_ERROR_RESULT(AllocationFailureInMakeUnique, 3422);
R_DEFINE_ERROR_RESULT(AllocationFailureInAllocateShared, 3423);
R_DEFINE_ERROR_RESULT(AllocationFailurePooledBufferNotEnoughSize, 3424);
R_DEFINE_ERROR_RANGE(Internal, 3000, 7999);
R_DEFINE_ERROR_RANGE(MmcAccessFailed, 3500, 3999);
@@ -284,12 +292,22 @@ namespace ams::fs {
R_DEFINE_ERROR_RESULT(GameCardLogoDataCorrupted, 4781);
R_DEFINE_ERROR_RANGE(Unexpected, 5000, 5999);
R_DEFINE_ERROR_RESULT(UnexpectedInAesCtrStorageA, 5315);
R_DEFINE_ERROR_RESULT(UnexpectedInAesXtsStorageA, 5316);
R_DEFINE_ERROR_RESULT(UnexpectedInFindFileSystemA, 5319);
R_DEFINE_ERROR_RESULT(UnexpectedInCompressedStorageA, 5324);
R_DEFINE_ERROR_RESULT(UnexpectedInCompressedStorageB, 5325);
R_DEFINE_ERROR_RESULT(UnexpectedInCompressedStorageC, 5326);
R_DEFINE_ERROR_RESULT(UnexpectedInLocalFileSystemA, 5305);
R_DEFINE_ERROR_RESULT(UnexpectedInLocalFileSystemB, 5306);
R_DEFINE_ERROR_RESULT(UnexpectedInLocalFileSystemC, 5307);
R_DEFINE_ERROR_RESULT(UnexpectedInLocalFileSystemD, 5308);
R_DEFINE_ERROR_RESULT(UnexpectedInLocalFileSystemE, 5309);
R_DEFINE_ERROR_RESULT(UnexpectedInLocalFileSystemF, 5310);
R_DEFINE_ERROR_RESULT(UnexpectedInPathOnExecutionDirectoryA, 5312);
R_DEFINE_ERROR_RESULT(UnexpectedInPathOnExecutionDirectoryB, 5313);
R_DEFINE_ERROR_RESULT(UnexpectedInPathOnExecutionDirectoryC, 5314);
R_DEFINE_ERROR_RESULT(UnexpectedInAesCtrStorageA, 5315);
R_DEFINE_ERROR_RESULT(UnexpectedInAesXtsStorageA, 5316);
R_DEFINE_ERROR_RESULT(UnexpectedInFindFileSystemA, 5319);
R_DEFINE_ERROR_RESULT(UnexpectedInCompressedStorageA, 5324);
R_DEFINE_ERROR_RESULT(UnexpectedInCompressedStorageB, 5325);
R_DEFINE_ERROR_RESULT(UnexpectedInCompressedStorageC, 5326);
R_DEFINE_ERROR_RESULT(UnexpectedInPathA, 5328);
R_DEFINE_ERROR_RANGE(PreconditionViolation, 6000, 6499);
R_DEFINE_ERROR_RANGE(InvalidArgument, 6001, 6199);
@@ -334,6 +352,7 @@ namespace ams::fs {
R_DEFINE_ERROR_RESULT(UnsupportedOperationInFileStorageA, 6306);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInFileStorageB, 6307);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInSwitchStorageA, 6308);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInStorageServiceObjectAdapterA, 6309);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInAesCtrCounterExtendedStorageA, 6310);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInAesCtrCounterExtendedStorageB, 6311);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInAesCtrCounterExtendedStorageC, 6312);
@@ -372,9 +391,12 @@ namespace ams::fs {
R_DEFINE_ERROR_RESULT(UnsupportedOperationInPartitionFileSystemB, 6375);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInPartitionFileA, 6376);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInPartitionFileB, 6377);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInLocalFileA, 6378);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInDirectorySaveDataFileSystemA, 6384);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInCompressedStorageA, 6387);
R_DEFINE_ERROR_RANGE(PermissionDenied, 6400, 6449);
R_DEFINE_ERROR_RESULT(PermissionDeniedForCreateHostFileSystem, 6403);
R_DEFINE_ERROR_RESULT(PortAcceptableCountLimited, 6450);
R_DEFINE_ERROR_RESULT(NeedFlush, 6454);

View File

@@ -23,6 +23,7 @@ namespace ams::os {
R_DEFINE_ERROR_RESULT(Busy, 4);
R_DEFINE_ERROR_RESULT(InvalidParameter, 7);
R_DEFINE_ERROR_RESULT(OutOfMemory, 8);
R_DEFINE_ERROR_RESULT(OutOfResource, 9);
@@ -41,4 +42,7 @@ namespace ams::os {
R_DEFINE_ERROR_RESULT(SessionClosedForReply, 511);
R_DEFINE_ERROR_RESULT(ReceiveListBroken, 512);
R_DEFINE_ERROR_RESULT(NotImplemented, 1000);
R_DEFINE_ERROR_RESULT(NotSupported, 1001);
}

View File

@@ -219,6 +219,14 @@ namespace ams {
}
#if defined(ATMOSPHERE_BOARD_NINTENDO_NX) && defined(ATMOSPHERE_ARCH_ARM64) && defined(ATMOSPHERE_IS_STRATOSPHERE)
namespace diag::impl {
void FatalErrorByResultForNx(Result result) noexcept NORETURN;
}
#endif
}
/* Macros for defining new results. */
@@ -353,61 +361,66 @@ namespace ams::result::impl {
/// Returns a result.
#define R_THROW(res_expr) \
({ \
{ \
const ::ams::Result _tmp_r_throw_rc = (res_expr); \
if constexpr (std::same_as<decltype(__TmpCurrentResultReference), ::ams::Result &>) { __TmpCurrentResultReference = _tmp_r_throw_rc; } \
return _tmp_r_throw_rc; \
})
}
/// Returns ResultSuccess()
#define R_SUCCEED() R_THROW(::ams::ResultSuccess())
/// Evaluates an expression that returns a result, and returns the result if it would fail.
#define R_TRY(res_expr) \
({ \
{ \
if (const auto _tmp_r_try_rc = (res_expr); R_FAILED(_tmp_r_try_rc)) { \
R_THROW(_tmp_r_try_rc); \
} \
})
}
/// Return a result.
#define R_RETURN(res_expr) R_THROW(res_expr)
#ifdef AMS_ENABLE_DEBUG_PRINT
#define AMS_CALL_ON_RESULT_ASSERTION_IMPL(cond, val) ::ams::result::impl::OnResultAssertion(__FILE__, __LINE__, __PRETTY_FUNCTION__, cond, val)
#define AMS_CALL_ON_RESULT_ABORT_IMPL(cond, val) ::ams::result::impl::OnResultAbort(__FILE__, __LINE__, __PRETTY_FUNCTION__, cond, val)
#if defined(ATMOSPHERE_BOARD_NINTENDO_NX) && defined(ATMOSPHERE_IS_STRATOSPHERE) && !defined(AMS_ENABLE_DETAILED_ASSERTIONS) && !defined(AMS_BUILD_FOR_DEBUGGING) && !defined(AMS_BUILD_FOR_AUDITING)
#define AMS_CALL_ON_RESULT_ASSERTION_IMPL(cond, val) do { ::ams::diag::impl::FatalErrorByResultForNx(val); AMS_INFINITE_LOOP(); AMS_ASSUME(false); } while (false)
#define AMS_CALL_ON_RESULT_ABORT_IMPL(cond, val) do { ::ams::diag::impl::FatalErrorByResultForNx(val); AMS_INFINITE_LOOP(); AMS_ASSUME(false); } while (false)
#else
#define AMS_CALL_ON_RESULT_ASSERTION_IMPL(cond, val) ::ams::result::impl::OnResultAssertion("", 0, "", "", val)
#define AMS_CALL_ON_RESULT_ABORT_IMPL(cond, val) ::ams::result::impl::OnResultAbort("", 0, "", "", val)
#if defined(AMS_ENABLE_DETAILED_ASSERTIONS)
#define AMS_CALL_ON_RESULT_ASSERTION_IMPL(cond, val) ::ams::result::impl::OnResultAssertion(__FILE__, __LINE__, __PRETTY_FUNCTION__, cond, val)
#define AMS_CALL_ON_RESULT_ABORT_IMPL(cond, val) ::ams::result::impl::OnResultAbort(__FILE__, __LINE__, __PRETTY_FUNCTION__, cond, val)
#else
#define AMS_CALL_ON_RESULT_ASSERTION_IMPL(cond, val) ::ams::result::impl::OnResultAssertion("", 0, "", "", val)
#define AMS_CALL_ON_RESULT_ABORT_IMPL(cond, val) ::ams::result::impl::OnResultAbort("", 0, "", "", val)
#endif
#endif
/// Evaluates an expression that returns a result, and asserts the result if it would fail.
#ifdef AMS_ENABLE_ASSERTIONS
#define R_ASSERT(res_expr) \
({ \
{ \
if (const auto _tmp_r_assert_rc = (res_expr); AMS_UNLIKELY(R_FAILED(_tmp_r_assert_rc))) { \
AMS_CALL_ON_RESULT_ASSERTION_IMPL(#res_expr, _tmp_r_assert_rc); \
} \
})
}
#else
#define R_ASSERT(res_expr) AMS_UNUSED((res_expr));
#endif
/// Evaluates an expression that returns a result, and aborts if the result would fail.
#define R_ABORT_UNLESS(res_expr) \
({ \
{ \
if (const auto _tmp_r_abort_rc = (res_expr); AMS_UNLIKELY(R_FAILED(_tmp_r_abort_rc))) { \
AMS_CALL_ON_RESULT_ABORT_IMPL(#res_expr, _tmp_r_abort_rc); \
} \
})
}
/// Evaluates a boolean expression, and returns a result unless that expression is true.
#define R_UNLESS(expr, res) \
({ \
{ \
if (!(expr)) { \
R_THROW(res); \
} \
})
}
/// Evaluates a boolean expression, and succeeds if that expression is true.
#define R_SUCCEED_IF(expr) R_UNLESS(!(expr), ResultSuccess())
@@ -415,24 +428,24 @@ namespace ams::result::impl {
/// Helpers for pattern-matching on a result expression, if the result would fail.
#define R_CURRENT_RESULT _tmp_r_try_catch_current_result
#define R_TRY_CATCH(res_expr) \
({ \
#define R_TRY_CATCH(res_expr) \
{ \
const auto R_CURRENT_RESULT = (res_expr); \
if (R_FAILED(R_CURRENT_RESULT)) { \
if (R_FAILED(R_CURRENT_RESULT)) { \
if (false)
#define R_CATCH(...) \
#define R_CATCH(...) \
} else if (::ams::result::impl::EvaluateAnyResultIncludes<__VA_ARGS__>(R_CURRENT_RESULT)) { \
if (true)
#define R_CATCH_MODULE(__module__) \
#define R_CATCH_MODULE(__module__) \
} else if ((R_CURRENT_RESULT).GetModule() == ::ams::R_NAMESPACE_MODULE_ID(__module__)) { \
if (true)
#define R_CONVERT(catch_type, convert_type) \
R_CATCH(catch_type) { R_THROW(static_cast<::ams::Result>(convert_type)); }
#define R_CATCH_ALL() \
#define R_CATCH_ALL() \
} else if (R_FAILED(R_CURRENT_RESULT)) { \
if (true)
@@ -442,26 +455,26 @@ namespace ams::result::impl {
#define R_CATCH_RETHROW(catch_type) \
R_CONVERT(catch_type, R_CURRENT_RESULT)
#define R_END_TRY_CATCH \
#define R_END_TRY_CATCH \
else if (R_FAILED(R_CURRENT_RESULT)) { \
R_THROW(R_CURRENT_RESULT); \
} \
} \
})
R_THROW(R_CURRENT_RESULT); \
} \
} \
}
#define R_END_TRY_CATCH_WITH_ASSERT \
else { \
#define R_END_TRY_CATCH_WITH_ASSERT \
else { \
R_ASSERT(R_CURRENT_RESULT); \
} \
} \
})
} \
} \
}
#define R_END_TRY_CATCH_WITH_ABORT_UNLESS \
else { \
#define R_END_TRY_CATCH_WITH_ABORT_UNLESS \
else { \
R_ABORT_UNLESS(R_CURRENT_RESULT); \
} \
} \
})
} \
} \
}

View File

@@ -19,8 +19,10 @@
#include <vapours/assert.hpp>
#include <vapours/results.hpp>
#if defined(ATMOSPHERE_OS_HORIZON)
#include <vapours/svc/svc_types.hpp>
#include <vapours/svc/svc_definitions.hpp>
#include <vapours/svc/svc_memory_map.hpp>
#include <vapours/svc/svc_version.hpp>
#include <vapours/svc/ipc/svc_message_buffer.hpp>
#endif

View File

@@ -17,7 +17,6 @@
#include <cstdint>
#include <cstddef>
#include <cstdbool>
#include <cstdalign>
/* NOTE: This file serves as a substitute for libnx <switch/types.h>. */

View File

@@ -52,7 +52,9 @@ namespace ams::util {
template<UsableAtomicType T>
using AtomicStorage = typename AtomicIntegerStorage<T>::Type;
static_assert(std::same_as<AtomicStorage<void *>, uintptr_t>);
static_assert(std::same_as<AtomicStorage<void *>, u64>);
static_assert(std::same_as<AtomicStorage<s8>, u8>);
static_assert(std::same_as<AtomicStorage<u8>, u8>);
static_assert(std::same_as<AtomicStorage<s16>, u16>);

View File

@@ -83,7 +83,7 @@ namespace ams::util {
template<std::memory_order Order = std::memory_order_seq_cst>
ALWAYS_INLINE void Store(T arg) {
return m_v.store(Order);
return m_v.store(arg, Order);
}
template<std::memory_order Order = std::memory_order_seq_cst>
@@ -135,6 +135,8 @@ namespace ams::util {
ALWAYS_INLINE T operator--(int) { static_assert(Enable == HasArithmeticFunctions); return this->FetchSub(1); }
};
/* TODO: Clang does not yet define std::atomic_ref, so if we want this we will have to implement it ourselves. */
#if !defined(ATMOSPHERE_COMPILER_CLANG)
template<impl::UsableAtomicType T>
class AtomicRef {
NON_MOVEABLE(AtomicRef);
@@ -218,6 +220,7 @@ namespace ams::util {
template<bool Enable = HasArithmeticFunctions, typename = typename std::enable_if<Enable, void>::type>
ALWAYS_INLINE T operator--(int) const { static_assert(Enable == HasArithmeticFunctions); return this->FetchSub(1); }
};
#endif
}

View File

@@ -49,32 +49,32 @@ namespace ams::util {
}
template<>
constexpr ALWAYS_INLINE void *AlignUp<void *>(void *value, size_t alignment) {
ALWAYS_INLINE void *AlignUp<void *>(void *value, size_t alignment) {
return reinterpret_cast<void *>(AlignUp(reinterpret_cast<uintptr_t>(value), alignment));
}
template<>
constexpr ALWAYS_INLINE const void *AlignUp<const void *>(const void *value, size_t alignment) {
ALWAYS_INLINE const void *AlignUp<const void *>(const void *value, size_t alignment) {
return reinterpret_cast<const void *>(AlignUp(reinterpret_cast<uintptr_t>(value), alignment));
}
template<>
constexpr ALWAYS_INLINE void *AlignDown<void *>(void *value, size_t alignment) {
ALWAYS_INLINE void *AlignDown<void *>(void *value, size_t alignment) {
return reinterpret_cast<void *>(AlignDown(reinterpret_cast<uintptr_t>(value), alignment));
}
template<>
constexpr ALWAYS_INLINE const void *AlignDown<const void *>(const void *value, size_t alignment) {
ALWAYS_INLINE const void *AlignDown<const void *>(const void *value, size_t alignment) {
return reinterpret_cast<void *>(AlignDown(reinterpret_cast<uintptr_t>(value), alignment));
}
template<>
constexpr ALWAYS_INLINE bool IsAligned<void *>(void *value, size_t alignment) {
ALWAYS_INLINE bool IsAligned<void *>(void *value, size_t alignment) {
return IsAligned(reinterpret_cast<uintptr_t>(value), alignment);
}
template<>
constexpr ALWAYS_INLINE bool IsAligned<const void *>(const void *value, size_t alignment) {
ALWAYS_INLINE bool IsAligned<const void *>(const void *value, size_t alignment) {
return IsAligned(reinterpret_cast<uintptr_t>(value), alignment);
}

View File

@@ -26,8 +26,143 @@ namespace ams::util {
CharacterEncodingResult_InvalidFormat = 2,
};
CharacterEncodingResult ConvertCharacterUtf8ToUtf32(u32 *dst, const char *src);
namespace impl {
CharacterEncodingResult PickOutCharacterFromUtf8String(char *dst, const char **str);
class CharacterEncodingHelper {
public:
static constexpr int8_t Utf8NBytesInnerTable[0x100 + 1] = {
-1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8,
};
static constexpr ALWAYS_INLINE char GetUtf8NBytes(size_t i) {
return static_cast<char>(Utf8NBytesInnerTable[1 + i]);
}
};
}
constexpr inline CharacterEncodingResult ConvertCharacterUtf8ToUtf32(u32 *dst, const char *src) {
/* Check pre-conditions. */
AMS_ASSERT(dst != nullptr);
AMS_ASSERT(src != nullptr);
/* Perform the conversion. */
const auto *p = src;
switch (impl::CharacterEncodingHelper::GetUtf8NBytes(static_cast<unsigned char>(p[0]))) {
case 1:
*dst = static_cast<u32>(p[0]);
return CharacterEncodingResult_Success;
case 2:
if ((static_cast<u32>(p[0]) & 0x1E) != 0) {
if (impl::CharacterEncodingHelper::GetUtf8NBytes(static_cast<unsigned char>(p[1])) == 0) {
*dst = (static_cast<u32>(p[0] & 0x1F) << 6) | (static_cast<u32>(p[1] & 0x3F) << 0);
return CharacterEncodingResult_Success;
}
}
break;
case 3:
if (impl::CharacterEncodingHelper::GetUtf8NBytes(static_cast<unsigned char>(p[1])) == 0 && impl::CharacterEncodingHelper::GetUtf8NBytes(static_cast<unsigned char>(p[2])) == 0) {
const u32 c = (static_cast<u32>(p[0] & 0xF) << 12) | (static_cast<u32>(p[1] & 0x3F) << 6) | (static_cast<u32>(p[2] & 0x3F) << 0);
if ((c & 0xF800) != 0 && (c & 0xF800) != 0xD800) {
*dst = c;
return CharacterEncodingResult_Success;
}
}
return CharacterEncodingResult_InvalidFormat;
case 4:
if (impl::CharacterEncodingHelper::GetUtf8NBytes(static_cast<unsigned char>(p[1])) == 0 && impl::CharacterEncodingHelper::GetUtf8NBytes(static_cast<unsigned char>(p[2])) == 0 && impl::CharacterEncodingHelper::GetUtf8NBytes(static_cast<unsigned char>(p[3])) == 0) {
const u32 c = (static_cast<u32>(p[0] & 0x7) << 18) | (static_cast<u32>(p[1] & 0x3F) << 12) | (static_cast<u32>(p[2] & 0x3F) << 6) | (static_cast<u32>(p[3] & 0x3F) << 0);
if (c >= 0x10000 && c < 0x110000) {
*dst = c;
return CharacterEncodingResult_Success;
}
}
return CharacterEncodingResult_InvalidFormat;
default:
break;
}
/* We failed to convert. */
return CharacterEncodingResult_InvalidFormat;
}
constexpr inline CharacterEncodingResult PickOutCharacterFromUtf8String(char *dst, const char **str) {
/* Check pre-conditions. */
AMS_ASSERT(dst != nullptr);
AMS_ASSERT(str != nullptr);
AMS_ASSERT(*str != nullptr);
/* Clear the output. */
dst[0] = 0;
dst[1] = 0;
dst[2] = 0;
dst[3] = 0;
/* Perform the conversion. */
const auto *p = *str;
u32 c = static_cast<u32>(*p);
switch (impl::CharacterEncodingHelper::GetUtf8NBytes(c)) {
case 1:
dst[0] = (*str)[0];
++(*str);
break;
case 2:
if ((p[0] & 0x1E) != 0) {
if (impl::CharacterEncodingHelper::GetUtf8NBytes(static_cast<unsigned char>(p[1])) == 0) {
c = (static_cast<u32>(p[0] & 0x1F) << 6) | (static_cast<u32>(p[1] & 0x3F) << 0);
dst[0] = (*str)[0];
dst[1] = (*str)[1];
(*str) += 2;
break;
}
}
return CharacterEncodingResult_InvalidFormat;
case 3:
if (impl::CharacterEncodingHelper::GetUtf8NBytes(static_cast<unsigned char>(p[1])) == 0 && impl::CharacterEncodingHelper::GetUtf8NBytes(static_cast<unsigned char>(p[2])) == 0) {
c = (static_cast<u32>(p[0] & 0xF) << 12) | (static_cast<u32>(p[1] & 0x3F) << 6) | (static_cast<u32>(p[2] & 0x3F) << 0);
if ((c & 0xF800) != 0 && (c & 0xF800) != 0xD800) {
dst[0] = (*str)[0];
dst[1] = (*str)[1];
dst[2] = (*str)[2];
(*str) += 3;
break;
}
}
return CharacterEncodingResult_InvalidFormat;
case 4:
if (impl::CharacterEncodingHelper::GetUtf8NBytes(static_cast<unsigned char>(p[1])) == 0 && impl::CharacterEncodingHelper::GetUtf8NBytes(static_cast<unsigned char>(p[2])) == 0 && impl::CharacterEncodingHelper::GetUtf8NBytes(static_cast<unsigned char>(p[3])) == 0) {
c = (static_cast<u32>(p[0] & 0x7) << 18) | (static_cast<u32>(p[1] & 0x3F) << 12) | (static_cast<u32>(p[2] & 0x3F) << 6) | (static_cast<u32>(p[3] & 0x3F) << 0);
if (c >= 0x10000 && c < 0x110000) {
dst[0] = (*str)[0];
dst[1] = (*str)[1];
dst[2] = (*str)[2];
dst[3] = (*str)[3];
(*str) += 4;
break;
}
}
return CharacterEncodingResult_InvalidFormat;
default:
return CharacterEncodingResult_InvalidFormat;
}
return CharacterEncodingResult_Success;
}
}

View File

@@ -21,8 +21,7 @@
namespace ams::util {
#pragma GCC push_options
#pragma GCC optimize ("-O3")
AMS_PRAGMA_BEGIN_OPTIMIZE_O3()
/* Forward declare implementation class for Node. */
namespace impl {
@@ -627,6 +626,6 @@ namespace ams::util {
}
};
#pragma GCC pop_options
AMS_PRAGMA_END_OPTIMIZE()
}

View File

@@ -22,8 +22,7 @@
namespace ams::util {
#pragma GCC push_options
#pragma GCC optimize ("-O3")
AMS_PRAGMA_BEGIN_OPTIMIZE_O3()
namespace impl {
@@ -583,6 +582,6 @@ namespace ams::util {
}
};
#pragma GCC pop_options
AMS_PRAGMA_END_OPTIMIZE()
}

View File

@@ -124,17 +124,47 @@ namespace ams::util {
template<auto MemberPtr, typename RealParentType = GetParentType<MemberPtr>> requires (std::derived_from<RealParentType, GetParentType<MemberPtr>> || std::same_as<RealParentType, GetParentType<MemberPtr>>)
struct OffsetOf : public std::integral_constant<std::ptrdiff_t, OffsetOfCalculator<RealParentType, GetMemberType<MemberPtr>, MemberPtr>::Value> {};
#if defined(ATMOSPHERE_COMPILER_CLANG)
template<typename ParentType, typename MemberType, auto Ptr>
struct OffsetOfCalculatorTheSadWayForClangSupport {
static ALWAYS_INLINE std::ptrdiff_t Calculate() {
const union Union {
ParentType p;
char c;
Union() : c() { /* ... */ }
~Union() { /* ... */ }
} U;
const auto *parent = std::addressof(U.p);
const auto *target = std::addressof(parent->*Ptr);
return static_cast<const uint8_t *>(static_cast<const void *>(target)) - static_cast<const uint8_t *>(static_cast<const void *>(parent));
}
};
#endif
}
template<auto MemberPtr, typename RealParentType = impl::GetParentType<MemberPtr>>
ALWAYS_INLINE RealParentType &GetParentReference(impl::GetMemberType<MemberPtr> *member) {
/* TODO: If clang resolves compiler-bugs in consteval (or if my std proposal makes it into a future C++ standard), we should go back to constexpr. */
#if defined(ATMOSPHERE_COMPILER_CLANG)
const std::ptrdiff_t Offset = impl::OffsetOfCalculatorTheSadWayForClangSupport<RealParentType, impl::GetMemberType<MemberPtr>, MemberPtr>::Calculate();
#else
constexpr std::ptrdiff_t Offset = impl::OffsetOf<MemberPtr, RealParentType>::value;
#endif
return *static_cast<RealParentType *>(static_cast<void *>(static_cast<uint8_t *>(static_cast<void *>(member)) - Offset));
}
template<auto MemberPtr, typename RealParentType = impl::GetParentType<MemberPtr>>
ALWAYS_INLINE RealParentType const &GetParentReference(impl::GetMemberType<MemberPtr> const *member) {
/* TODO: If clang resolves compiler-bugs in consteval (or if my std proposal makes it into a future C++ standard), we should go back to constexpr. */
#if defined(ATMOSPHERE_COMPILER_CLANG)
const std::ptrdiff_t Offset = impl::OffsetOfCalculatorTheSadWayForClangSupport<RealParentType, impl::GetMemberType<MemberPtr>, MemberPtr>::Calculate();
#else
constexpr std::ptrdiff_t Offset = impl::OffsetOf<MemberPtr, RealParentType>::value;
#endif
return *static_cast<const RealParentType *>(static_cast<const void *>(static_cast<const uint8_t *>(static_cast<const void *>(member)) - Offset));
}

View File

@@ -88,6 +88,18 @@ namespace ams::util {
return static_cast<int>(cur - src);
}
template<typename T>
constexpr int Strlen(const T *str) {
AMS_ASSERT(str != nullptr);
int length = 0;
while (*str++) {
++length;
}
return length;
}
template<typename T>
constexpr int Strnlen(const T *str, int count) {
AMS_ASSERT(str != nullptr);
@@ -101,4 +113,50 @@ namespace ams::util {
return length;
}
#if defined(ATMOSPHERE_IS_STRATOSPHERE)
ALWAYS_INLINE void *Memchr(void *s, int c, size_t n) {
return const_cast<void*>(::memchr(s, c, n));
}
ALWAYS_INLINE const void *Memchr(const void *s, int c, size_t n) {
return ::memchr(s, c, n);
}
inline void *Memrchr(void *s, int c, size_t n) {
#if !(defined(__MINGW32__) || defined(__MINGW64__) || defined(ATMOSPHERE_OS_MACOS))
return const_cast<void *>(::memrchr(s, c, n));
#else
/* TODO: Optimized implementation? */
if (AMS_LIKELY(n > 0)) {
const u8 *p = static_cast<const u8 *>(s);
const u8 v = static_cast<u8>(c);
while ((n--) != 0) {
if (p[n] == v) {
return const_cast<void *>(static_cast<const void *>(p + n));
}
}
}
return nullptr;
#endif
}
inline const void *Memrchr(const void *s, int c, size_t n) {
#if !(defined(__MINGW32__) || defined(__MINGW64__) || defined(ATMOSPHERE_OS_MACOS))
return ::memrchr(s, c, n);
#else
/* TODO: Optimized implementation? */
if (AMS_LIKELY(n > 0)) {
const u8 *p = static_cast<const u8 *>(s);
const u8 v = static_cast<u8>(c);
while ((n--) != 0) {
if (p[n] == v) {
return static_cast<const void *>(p + n);
}
}
}
return nullptr;
#endif
}
#endif
}