ams: support building unit test programs on windows/linux/macos
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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__); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
24
libraries/libvapours/include/vapours/compiler.hpp
Normal file
24
libraries/libvapours/include/vapours/compiler.hpp
Normal 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
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
}
|
||||
|
||||
@@ -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>); */
|
||||
|
||||
@@ -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>);
|
||||
|
||||
@@ -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)>>);
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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__)
|
||||
@@ -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__)
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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); \
|
||||
} \
|
||||
} \
|
||||
})
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -17,7 +17,6 @@
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <cstdbool>
|
||||
#include <cstdalign>
|
||||
|
||||
/* NOTE: This file serves as a substitute for libnx <switch/types.h>. */
|
||||
|
||||
|
||||
@@ -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>);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user