ams: take care of most TODO C++20s
This commit is contained in:
@@ -30,11 +30,9 @@ namespace ams::util {
|
||||
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <typename T> requires std::integral<T>
|
||||
class BitsOf {
|
||||
private:
|
||||
static_assert(std::is_integral<T>::value);
|
||||
|
||||
static constexpr ALWAYS_INLINE int GetLsbPos(T v) {
|
||||
return __builtin_ctzll(static_cast<u64>(v));
|
||||
}
|
||||
@@ -78,69 +76,68 @@ namespace ams::util {
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T = u64, typename ...Args>
|
||||
template<typename T = u64, typename ...Args> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T CombineBits(Args... args) {
|
||||
return (... | (T(1u) << args));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T ResetLeastSignificantOneBit(T x) {
|
||||
return x & (x - 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T SetLeastSignificantZeroBit(T x) {
|
||||
return x | (x + 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T LeastSignificantOneBit(T x) {
|
||||
return x & ~(x - 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T LeastSignificantZeroBit(T x) {
|
||||
return ~x & (x + 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T ResetTrailingOnes(T x) {
|
||||
return x & (x + 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T SetTrailingZeros(T x) {
|
||||
return x | (x - 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T MaskTrailingZeros(T x) {
|
||||
return (~x) & (x - 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T MaskTrailingOnes(T x) {
|
||||
return ~((~x) | (x + 1));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T MaskTrailingZerosAndLeastSignificantOneBit(T x) {
|
||||
return x ^ (x - 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T MaskTrailingOnesAndLeastSignificantZeroBit(T x) {
|
||||
return x ^ (x + 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE int PopCount(T x) {
|
||||
/* TODO: C++20 std::bit_cast */
|
||||
using U = typename std::make_unsigned<T>::type;
|
||||
U u = static_cast<U>(x);
|
||||
|
||||
/* TODO: C++20 std::is_constant_evaluated */
|
||||
if (false) {
|
||||
if (std::is_constant_evaluated()) {
|
||||
/* https://en.wikipedia.org/wiki/Hamming_weight */
|
||||
constexpr U m1 = U(-1) / 0x03;
|
||||
constexpr U m2 = U(-1) / 0x05;
|
||||
@@ -168,10 +165,9 @@ namespace ams::util {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE int CountLeadingZeros(T x) {
|
||||
/* TODO: C++20 std::is_constant_evaluated */
|
||||
if (false) {
|
||||
if (std::is_constant_evaluated()) {
|
||||
for (size_t i = 0; i < impl::Log2<BITSIZEOF(T)>; ++i) {
|
||||
const size_t shift = (0x1 << i);
|
||||
x |= x >> shift;
|
||||
@@ -195,18 +191,18 @@ namespace ams::util {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE bool IsPowerOfTwo(T x) {
|
||||
return x > 0 && ResetLeastSignificantOneBit(x) == 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T CeilingPowerOfTwo(T x) {
|
||||
AMS_ASSERT(x > 0);
|
||||
return T(1) << (BITSIZEOF(T) - CountLeadingZeros(T(x - 1)));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T FloorPowerOfTwo(T x) {
|
||||
AMS_ASSERT(x > 0);
|
||||
return T(1) << (BITSIZEOF(T) - CountLeadingZeros(x) - 1);
|
||||
|
||||
@@ -20,27 +20,17 @@
|
||||
|
||||
namespace ams::util {
|
||||
|
||||
/* TODO: C++20 std::endian */
|
||||
|
||||
constexpr bool IsLittleEndian() {
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
return std::endian::native == std::endian::little;
|
||||
}
|
||||
|
||||
constexpr bool IsBigEndian() {
|
||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
return std::endian::native == std::endian::big;
|
||||
}
|
||||
|
||||
static_assert(IsLittleEndian() ^ IsBigEndian());
|
||||
|
||||
template<typename U> /* requires unsigned_integral<U> */
|
||||
template<typename U> requires std::unsigned_integral<U>
|
||||
constexpr ALWAYS_INLINE U SwapBytes(const U u) {
|
||||
static_assert(BITSIZEOF(u8) == 8);
|
||||
constexpr U ByteMask = 0xFFu;
|
||||
@@ -85,14 +75,14 @@ namespace ams::util {
|
||||
((u & (ByteMask << 0)) << 40);
|
||||
}
|
||||
|
||||
template<typename T> /* requires integral<T> */
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE void SwapBytes(T *ptr) {
|
||||
using U = typename std::make_unsigned<T>::type;
|
||||
|
||||
*ptr = static_cast<T>(SwapBytes(static_cast<U>(*ptr)));
|
||||
}
|
||||
|
||||
template<typename T> /* requires integral<T> */
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T ConvertToBigEndian(const T val) {
|
||||
using U = typename std::make_unsigned<T>::type;
|
||||
|
||||
@@ -104,7 +94,7 @@ namespace ams::util {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> /* requires integral<T> */
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T ConvertToLittleEndian(const T val) {
|
||||
using U = typename std::make_unsigned<T>::type;
|
||||
|
||||
@@ -116,7 +106,7 @@ namespace ams::util {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> /* requires integral<T> */
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T ConvertToBigEndian48(const T val) {
|
||||
using U = typename std::make_unsigned<T>::type;
|
||||
static_assert(sizeof(T) == sizeof(u64));
|
||||
@@ -130,7 +120,7 @@ namespace ams::util {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> /* requires integral<T> */
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T ConvertToLittleEndian48(const T val) {
|
||||
using U = typename std::make_unsigned<T>::type;
|
||||
static_assert(sizeof(T) == sizeof(u64));
|
||||
@@ -144,12 +134,12 @@ namespace ams::util {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> /* requires integral<T> */
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T LoadBigEndian(T *ptr) {
|
||||
return ConvertToBigEndian(*ptr);
|
||||
}
|
||||
|
||||
template<typename T> /* requires integral<T> */
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T LoadLittleEndian(T *ptr) {
|
||||
return ConvertToLittleEndian(*ptr);
|
||||
}
|
||||
|
||||
@@ -17,16 +17,14 @@
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util/util_endian.hpp>
|
||||
|
||||
namespace ams::util {
|
||||
|
||||
template<char A, char B, char C, char D>
|
||||
struct FourCC {
|
||||
/* TODO: C++20 std::endian */
|
||||
static constexpr u32 Code = (static_cast<u32>(A) << 0x00) |
|
||||
(static_cast<u32>(B) << 0x08) |
|
||||
(static_cast<u32>(C) << 0x10) |
|
||||
(static_cast<u32>(D) << 0x18);
|
||||
static constexpr u32 Code = IsLittleEndian() ? ((static_cast<u32>(A) << 0x00) | (static_cast<u32>(B) << 0x08) | (static_cast<u32>(C) << 0x10) | (static_cast<u32>(D) << 0x18))
|
||||
: ((static_cast<u32>(A) << 0x18) | (static_cast<u32>(B) << 0x10) | (static_cast<u32>(C) << 0x08) | (static_cast<u32>(D) << 0x00));
|
||||
|
||||
static constexpr const char String[] = {A, B, C, D};
|
||||
|
||||
@@ -36,11 +34,8 @@ namespace ams::util {
|
||||
|
||||
template<char A, char B, char C, char D>
|
||||
struct ReverseFourCC {
|
||||
/* TODO: C++20 std::endian */
|
||||
static constexpr u32 Code = (static_cast<u32>(A) << 0x18) |
|
||||
(static_cast<u32>(B) << 0x10) |
|
||||
(static_cast<u32>(C) << 0x08) |
|
||||
(static_cast<u32>(D) << 0x00);
|
||||
static constexpr u32 Code = IsLittleEndian() ? ((static_cast<u32>(A) << 0x18) | (static_cast<u32>(B) << 0x10) | (static_cast<u32>(C) << 0x08) | (static_cast<u32>(D) << 0x00))
|
||||
: ((static_cast<u32>(A) << 0x00) | (static_cast<u32>(B) << 0x08) | (static_cast<u32>(C) << 0x10) | (static_cast<u32>(D) << 0x18));
|
||||
|
||||
static constexpr const char String[] = {D, C, B, A};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user