1
1
Fork 0
forked from suyu/suyu

common: Make use of [[nodiscard]] where applicable

Now that clang-format makes [[nodiscard]] attributes format sensibly, we
can apply them to several functions within the common library to allow
the compiler to complain about any misuses of the functions.
This commit is contained in:
Lioncash 2020-08-14 09:38:45 -04:00
parent 2b601e8636
commit df72480395
34 changed files with 343 additions and 358 deletions

View file

@ -15,7 +15,8 @@
namespace Common { namespace Common {
template <class ForwardIt, class T, class Compare = std::less<>> template <class ForwardIt, class T, class Compare = std::less<>>
ForwardIt BinaryFind(ForwardIt first, ForwardIt last, const T& value, Compare comp = {}) { [[nodiscard]] ForwardIt BinaryFind(ForwardIt first, ForwardIt last, const T& value,
Compare comp = {}) {
// Note: BOTH type T and the type after ForwardIt is dereferenced // Note: BOTH type T and the type after ForwardIt is dereferenced
// must be implicitly convertible to BOTH Type1 and Type2, used in Compare. // must be implicitly convertible to BOTH Type1 and Type2, used in Compare.
// This is stricter than lower_bound requirement (see above) // This is stricter than lower_bound requirement (see above)

View file

@ -9,7 +9,7 @@
namespace Common { namespace Common {
template <typename T> template <typename T>
constexpr T AlignUp(T value, std::size_t size) { [[nodiscard]] constexpr T AlignUp(T value, std::size_t size) {
static_assert(std::is_unsigned_v<T>, "T must be an unsigned value."); static_assert(std::is_unsigned_v<T>, "T must be an unsigned value.");
auto mod{static_cast<T>(value % size)}; auto mod{static_cast<T>(value % size)};
value -= mod; value -= mod;
@ -17,31 +17,31 @@ constexpr T AlignUp(T value, std::size_t size) {
} }
template <typename T> template <typename T>
constexpr T AlignDown(T value, std::size_t size) { [[nodiscard]] constexpr T AlignDown(T value, std::size_t size) {
static_assert(std::is_unsigned_v<T>, "T must be an unsigned value."); static_assert(std::is_unsigned_v<T>, "T must be an unsigned value.");
return static_cast<T>(value - value % size); return static_cast<T>(value - value % size);
} }
template <typename T> template <typename T>
constexpr T AlignBits(T value, std::size_t align) { [[nodiscard]] constexpr T AlignBits(T value, std::size_t align) {
static_assert(std::is_unsigned_v<T>, "T must be an unsigned value."); static_assert(std::is_unsigned_v<T>, "T must be an unsigned value.");
return static_cast<T>((value + ((1ULL << align) - 1)) >> align << align); return static_cast<T>((value + ((1ULL << align) - 1)) >> align << align);
} }
template <typename T> template <typename T>
constexpr bool Is4KBAligned(T value) { [[nodiscard]] constexpr bool Is4KBAligned(T value) {
static_assert(std::is_unsigned_v<T>, "T must be an unsigned value."); static_assert(std::is_unsigned_v<T>, "T must be an unsigned value.");
return (value & 0xFFF) == 0; return (value & 0xFFF) == 0;
} }
template <typename T> template <typename T>
constexpr bool IsWordAligned(T value) { [[nodiscard]] constexpr bool IsWordAligned(T value) {
static_assert(std::is_unsigned_v<T>, "T must be an unsigned value."); static_assert(std::is_unsigned_v<T>, "T must be an unsigned value.");
return (value & 0b11) == 0; return (value & 0b11) == 0;
} }
template <typename T> template <typename T>
constexpr bool IsAligned(T value, std::size_t alignment) { [[nodiscard]] constexpr bool IsAligned(T value, std::size_t alignment) {
using U = typename std::make_unsigned<T>::type; using U = typename std::make_unsigned<T>::type;
const U mask = static_cast<U>(alignment - 1); const U mask = static_cast<U>(alignment - 1);
return (value & mask) == 0; return (value & mask) == 0;
@ -64,7 +64,7 @@ public:
template <typename T2> template <typename T2>
constexpr AlignmentAllocator(const AlignmentAllocator<T2, Align>&) noexcept {} constexpr AlignmentAllocator(const AlignmentAllocator<T2, Align>&) noexcept {}
T* allocate(size_type n) { [[nodiscard]] T* allocate(size_type n) {
return static_cast<T*>(::operator new (n * sizeof(T), std::align_val_t{Align})); return static_cast<T*>(::operator new (n * sizeof(T), std::align_val_t{Align}));
} }

View file

@ -8,10 +8,10 @@
namespace Common { namespace Common {
bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected); [[nodiscard]] bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected);
bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected); [[nodiscard]] bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected);
bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected); [[nodiscard]] bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected);
bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected); [[nodiscard]] bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected);
bool AtomicCompareAndSwap(volatile u64* pointer, u128 value, u128 expected); [[nodiscard]] bool AtomicCompareAndSwap(volatile u64* pointer, u128 value, u128 expected);
} // namespace Common } // namespace Common

View file

@ -36,13 +36,6 @@
#include "common/common_funcs.h" #include "common/common_funcs.h"
#include "common/swap.h" #include "common/swap.h"
// Inlining
#ifdef _WIN32
#define FORCE_INLINE __forceinline
#else
#define FORCE_INLINE inline __attribute__((always_inline))
#endif
/* /*
* Abstract bitfield class * Abstract bitfield class
* *
@ -142,8 +135,8 @@ public:
* containing several bitfields can be assembled by formatting each of their values and ORing * containing several bitfields can be assembled by formatting each of their values and ORing
* the results together. * the results together.
*/ */
static constexpr FORCE_INLINE StorageType FormatValue(const T& value) { [[nodiscard]] static constexpr StorageType FormatValue(const T& value) {
return ((StorageType)value << position) & mask; return (static_cast<StorageType>(value) << position) & mask;
} }
/** /**
@ -151,7 +144,7 @@ public:
* (such as Value() or operator T), but this can be used to extract a value from a bitfield * (such as Value() or operator T), but this can be used to extract a value from a bitfield
* union in a constexpr context. * union in a constexpr context.
*/ */
static constexpr FORCE_INLINE T ExtractValue(const StorageType& storage) { [[nodiscard]] static constexpr T ExtractValue(const StorageType& storage) {
if constexpr (std::numeric_limits<UnderlyingType>::is_signed) { if constexpr (std::numeric_limits<UnderlyingType>::is_signed) {
std::size_t shift = 8 * sizeof(T) - bits; std::size_t shift = 8 * sizeof(T) - bits;
return static_cast<T>(static_cast<UnderlyingType>(storage << (shift - position)) >> return static_cast<T>(static_cast<UnderlyingType>(storage << (shift - position)) >>
@ -175,7 +168,7 @@ public:
constexpr BitField(BitField&&) noexcept = default; constexpr BitField(BitField&&) noexcept = default;
constexpr BitField& operator=(BitField&&) noexcept = default; constexpr BitField& operator=(BitField&&) noexcept = default;
constexpr operator T() const { [[nodiscard]] constexpr operator T() const {
return Value(); return Value();
} }
@ -183,11 +176,11 @@ public:
storage = static_cast<StorageType>((storage & ~mask) | FormatValue(value)); storage = static_cast<StorageType>((storage & ~mask) | FormatValue(value));
} }
constexpr T Value() const { [[nodiscard]] constexpr T Value() const {
return ExtractValue(storage); return ExtractValue(storage);
} }
constexpr explicit operator bool() const { [[nodiscard]] constexpr explicit operator bool() const {
return Value() != 0; return Value() != 0;
} }

View file

@ -17,12 +17,12 @@ namespace Common {
/// Gets the size of a specified type T in bits. /// Gets the size of a specified type T in bits.
template <typename T> template <typename T>
constexpr std::size_t BitSize() { [[nodiscard]] constexpr std::size_t BitSize() {
return sizeof(T) * CHAR_BIT; return sizeof(T) * CHAR_BIT;
} }
#ifdef _MSC_VER #ifdef _MSC_VER
inline u32 CountLeadingZeroes32(u32 value) { [[nodiscard]] inline u32 CountLeadingZeroes32(u32 value) {
unsigned long leading_zero = 0; unsigned long leading_zero = 0;
if (_BitScanReverse(&leading_zero, value) != 0) { if (_BitScanReverse(&leading_zero, value) != 0) {
@ -32,7 +32,7 @@ inline u32 CountLeadingZeroes32(u32 value) {
return 32; return 32;
} }
inline u32 CountLeadingZeroes64(u64 value) { [[nodiscard]] inline u32 CountLeadingZeroes64(u64 value) {
unsigned long leading_zero = 0; unsigned long leading_zero = 0;
if (_BitScanReverse64(&leading_zero, value) != 0) { if (_BitScanReverse64(&leading_zero, value) != 0) {
@ -42,7 +42,7 @@ inline u32 CountLeadingZeroes64(u64 value) {
return 64; return 64;
} }
#else #else
inline u32 CountLeadingZeroes32(u32 value) { [[nodiscard]] inline u32 CountLeadingZeroes32(u32 value) {
if (value == 0) { if (value == 0) {
return 32; return 32;
} }
@ -50,7 +50,7 @@ inline u32 CountLeadingZeroes32(u32 value) {
return static_cast<u32>(__builtin_clz(value)); return static_cast<u32>(__builtin_clz(value));
} }
inline u32 CountLeadingZeroes64(u64 value) { [[nodiscard]] inline u32 CountLeadingZeroes64(u64 value) {
if (value == 0) { if (value == 0) {
return 64; return 64;
} }
@ -60,7 +60,7 @@ inline u32 CountLeadingZeroes64(u64 value) {
#endif #endif
#ifdef _MSC_VER #ifdef _MSC_VER
inline u32 CountTrailingZeroes32(u32 value) { [[nodiscard]] inline u32 CountTrailingZeroes32(u32 value) {
unsigned long trailing_zero = 0; unsigned long trailing_zero = 0;
if (_BitScanForward(&trailing_zero, value) != 0) { if (_BitScanForward(&trailing_zero, value) != 0) {
@ -70,7 +70,7 @@ inline u32 CountTrailingZeroes32(u32 value) {
return 32; return 32;
} }
inline u32 CountTrailingZeroes64(u64 value) { [[nodiscard]] inline u32 CountTrailingZeroes64(u64 value) {
unsigned long trailing_zero = 0; unsigned long trailing_zero = 0;
if (_BitScanForward64(&trailing_zero, value) != 0) { if (_BitScanForward64(&trailing_zero, value) != 0) {
@ -80,7 +80,7 @@ inline u32 CountTrailingZeroes64(u64 value) {
return 64; return 64;
} }
#else #else
inline u32 CountTrailingZeroes32(u32 value) { [[nodiscard]] inline u32 CountTrailingZeroes32(u32 value) {
if (value == 0) { if (value == 0) {
return 32; return 32;
} }
@ -88,7 +88,7 @@ inline u32 CountTrailingZeroes32(u32 value) {
return static_cast<u32>(__builtin_ctz(value)); return static_cast<u32>(__builtin_ctz(value));
} }
inline u32 CountTrailingZeroes64(u64 value) { [[nodiscard]] inline u32 CountTrailingZeroes64(u64 value) {
if (value == 0) { if (value == 0) {
return 64; return 64;
} }
@ -99,13 +99,13 @@ inline u32 CountTrailingZeroes64(u64 value) {
#ifdef _MSC_VER #ifdef _MSC_VER
inline u32 MostSignificantBit32(const u32 value) { [[nodiscard]] inline u32 MostSignificantBit32(const u32 value) {
unsigned long result; unsigned long result;
_BitScanReverse(&result, value); _BitScanReverse(&result, value);
return static_cast<u32>(result); return static_cast<u32>(result);
} }
inline u32 MostSignificantBit64(const u64 value) { [[nodiscard]] inline u32 MostSignificantBit64(const u64 value) {
unsigned long result; unsigned long result;
_BitScanReverse64(&result, value); _BitScanReverse64(&result, value);
return static_cast<u32>(result); return static_cast<u32>(result);
@ -113,30 +113,30 @@ inline u32 MostSignificantBit64(const u64 value) {
#else #else
inline u32 MostSignificantBit32(const u32 value) { [[nodiscard]] inline u32 MostSignificantBit32(const u32 value) {
return 31U - static_cast<u32>(__builtin_clz(value)); return 31U - static_cast<u32>(__builtin_clz(value));
} }
inline u32 MostSignificantBit64(const u64 value) { [[nodiscard]] inline u32 MostSignificantBit64(const u64 value) {
return 63U - static_cast<u32>(__builtin_clzll(value)); return 63U - static_cast<u32>(__builtin_clzll(value));
} }
#endif #endif
inline u32 Log2Floor32(const u32 value) { [[nodiscard]] inline u32 Log2Floor32(const u32 value) {
return MostSignificantBit32(value); return MostSignificantBit32(value);
} }
inline u32 Log2Ceil32(const u32 value) { [[nodiscard]] inline u32 Log2Ceil32(const u32 value) {
const u32 log2_f = Log2Floor32(value); const u32 log2_f = Log2Floor32(value);
return log2_f + ((value ^ (1U << log2_f)) != 0U); return log2_f + ((value ^ (1U << log2_f)) != 0U);
} }
inline u32 Log2Floor64(const u64 value) { [[nodiscard]] inline u32 Log2Floor64(const u64 value) {
return MostSignificantBit64(value); return MostSignificantBit64(value);
} }
inline u32 Log2Ceil64(const u64 value) { [[nodiscard]] inline u32 Log2Ceil64(const u64 value) {
const u64 log2_f = static_cast<u64>(Log2Floor64(value)); const u64 log2_f = static_cast<u64>(Log2Floor64(value));
return static_cast<u32>(log2_f + ((value ^ (1ULL << log2_f)) != 0ULL)); return static_cast<u32>(log2_f + ((value ^ (1ULL << log2_f)) != 0ULL));
} }

View file

@ -61,42 +61,43 @@
#pragma once #pragma once
#include <cstddef>
#include <cstdint>
#include <utility> #include <utility>
#include <stdint.h>
#include <stdlib.h> // for std::size_t.
namespace Common { namespace Common {
typedef std::pair<uint64_t, uint64_t> uint128; using uint128 = std::pair<uint64_t, uint64_t>;
inline uint64_t Uint128Low64(const uint128& x) { [[nodiscard]] inline uint64_t Uint128Low64(const uint128& x) {
return x.first; return x.first;
} }
inline uint64_t Uint128High64(const uint128& x) { [[nodiscard]] inline uint64_t Uint128High64(const uint128& x) {
return x.second; return x.second;
} }
// Hash function for a byte array. // Hash function for a byte array.
uint64_t CityHash64(const char* buf, std::size_t len); [[nodiscard]] uint64_t CityHash64(const char* buf, std::size_t len);
// Hash function for a byte array. For convenience, a 64-bit seed is also // Hash function for a byte array. For convenience, a 64-bit seed is also
// hashed into the result. // hashed into the result.
uint64_t CityHash64WithSeed(const char* buf, std::size_t len, uint64_t seed); [[nodiscard]] uint64_t CityHash64WithSeed(const char* buf, std::size_t len, uint64_t seed);
// Hash function for a byte array. For convenience, two seeds are also // Hash function for a byte array. For convenience, two seeds are also
// hashed into the result. // hashed into the result.
uint64_t CityHash64WithSeeds(const char* buf, std::size_t len, uint64_t seed0, uint64_t seed1); [[nodiscard]] uint64_t CityHash64WithSeeds(const char* buf, std::size_t len, uint64_t seed0,
uint64_t seed1);
// Hash function for a byte array. // Hash function for a byte array.
uint128 CityHash128(const char* s, std::size_t len); [[nodiscard]] uint128 CityHash128(const char* s, std::size_t len);
// Hash function for a byte array. For convenience, a 128-bit seed is also // Hash function for a byte array. For convenience, a 128-bit seed is also
// hashed into the result. // hashed into the result.
uint128 CityHash128WithSeed(const char* s, std::size_t len, uint128 seed); [[nodiscard]] uint128 CityHash128WithSeed(const char* s, std::size_t len, uint128 seed);
// Hash 128 input bits down to 64 bits of output. // Hash 128 input bits down to 64 bits of output.
// This is intended to be a reasonably good hash function. // This is intended to be a reasonably good hash function.
inline uint64_t Hash128to64(const uint128& x) { [[nodiscard]] inline uint64_t Hash128to64(const uint128& x) {
// Murmur-inspired hashing. // Murmur-inspired hashing.
const uint64_t kMul = 0x9ddfea08eb382d69ULL; const uint64_t kMul = 0x9ddfea08eb382d69ULL;
uint64_t a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul; uint64_t a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul;

View file

@ -13,42 +13,42 @@
namespace Color { namespace Color {
/// Convert a 1-bit color component to 8 bit /// Convert a 1-bit color component to 8 bit
constexpr u8 Convert1To8(u8 value) { [[nodiscard]] constexpr u8 Convert1To8(u8 value) {
return value * 255; return value * 255;
} }
/// Convert a 4-bit color component to 8 bit /// Convert a 4-bit color component to 8 bit
constexpr u8 Convert4To8(u8 value) { [[nodiscard]] constexpr u8 Convert4To8(u8 value) {
return (value << 4) | value; return (value << 4) | value;
} }
/// Convert a 5-bit color component to 8 bit /// Convert a 5-bit color component to 8 bit
constexpr u8 Convert5To8(u8 value) { [[nodiscard]] constexpr u8 Convert5To8(u8 value) {
return (value << 3) | (value >> 2); return (value << 3) | (value >> 2);
} }
/// Convert a 6-bit color component to 8 bit /// Convert a 6-bit color component to 8 bit
constexpr u8 Convert6To8(u8 value) { [[nodiscard]] constexpr u8 Convert6To8(u8 value) {
return (value << 2) | (value >> 4); return (value << 2) | (value >> 4);
} }
/// Convert a 8-bit color component to 1 bit /// Convert a 8-bit color component to 1 bit
constexpr u8 Convert8To1(u8 value) { [[nodiscard]] constexpr u8 Convert8To1(u8 value) {
return value >> 7; return value >> 7;
} }
/// Convert a 8-bit color component to 4 bit /// Convert a 8-bit color component to 4 bit
constexpr u8 Convert8To4(u8 value) { [[nodiscard]] constexpr u8 Convert8To4(u8 value) {
return value >> 4; return value >> 4;
} }
/// Convert a 8-bit color component to 5 bit /// Convert a 8-bit color component to 5 bit
constexpr u8 Convert8To5(u8 value) { [[nodiscard]] constexpr u8 Convert8To5(u8 value) {
return value >> 3; return value >> 3;
} }
/// Convert a 8-bit color component to 6 bit /// Convert a 8-bit color component to 6 bit
constexpr u8 Convert8To6(u8 value) { [[nodiscard]] constexpr u8 Convert8To6(u8 value) {
return value >> 2; return value >> 2;
} }
@ -57,7 +57,7 @@ constexpr u8 Convert8To6(u8 value) {
* @param bytes Pointer to encoded source color * @param bytes Pointer to encoded source color
* @return Result color decoded as Common::Vec4<u8> * @return Result color decoded as Common::Vec4<u8>
*/ */
inline Common::Vec4<u8> DecodeRGBA8(const u8* bytes) { [[nodiscard]] inline Common::Vec4<u8> DecodeRGBA8(const u8* bytes) {
return {bytes[3], bytes[2], bytes[1], bytes[0]}; return {bytes[3], bytes[2], bytes[1], bytes[0]};
} }
@ -66,7 +66,7 @@ inline Common::Vec4<u8> DecodeRGBA8(const u8* bytes) {
* @param bytes Pointer to encoded source color * @param bytes Pointer to encoded source color
* @return Result color decoded as Common::Vec4<u8> * @return Result color decoded as Common::Vec4<u8>
*/ */
inline Common::Vec4<u8> DecodeRGB8(const u8* bytes) { [[nodiscard]] inline Common::Vec4<u8> DecodeRGB8(const u8* bytes) {
return {bytes[2], bytes[1], bytes[0], 255}; return {bytes[2], bytes[1], bytes[0], 255};
} }
@ -75,7 +75,7 @@ inline Common::Vec4<u8> DecodeRGB8(const u8* bytes) {
* @param bytes Pointer to encoded source color * @param bytes Pointer to encoded source color
* @return Result color decoded as Common::Vec4<u8> * @return Result color decoded as Common::Vec4<u8>
*/ */
inline Common::Vec4<u8> DecodeRG8(const u8* bytes) { [[nodiscard]] inline Common::Vec4<u8> DecodeRG8(const u8* bytes) {
return {bytes[1], bytes[0], 0, 255}; return {bytes[1], bytes[0], 0, 255};
} }
@ -84,7 +84,7 @@ inline Common::Vec4<u8> DecodeRG8(const u8* bytes) {
* @param bytes Pointer to encoded source color * @param bytes Pointer to encoded source color
* @return Result color decoded as Common::Vec4<u8> * @return Result color decoded as Common::Vec4<u8>
*/ */
inline Common::Vec4<u8> DecodeRGB565(const u8* bytes) { [[nodiscard]] inline Common::Vec4<u8> DecodeRGB565(const u8* bytes) {
u16_le pixel; u16_le pixel;
std::memcpy(&pixel, bytes, sizeof(pixel)); std::memcpy(&pixel, bytes, sizeof(pixel));
return {Convert5To8((pixel >> 11) & 0x1F), Convert6To8((pixel >> 5) & 0x3F), return {Convert5To8((pixel >> 11) & 0x1F), Convert6To8((pixel >> 5) & 0x3F),
@ -96,7 +96,7 @@ inline Common::Vec4<u8> DecodeRGB565(const u8* bytes) {
* @param bytes Pointer to encoded source color * @param bytes Pointer to encoded source color
* @return Result color decoded as Common::Vec4<u8> * @return Result color decoded as Common::Vec4<u8>
*/ */
inline Common::Vec4<u8> DecodeRGB5A1(const u8* bytes) { [[nodiscard]] inline Common::Vec4<u8> DecodeRGB5A1(const u8* bytes) {
u16_le pixel; u16_le pixel;
std::memcpy(&pixel, bytes, sizeof(pixel)); std::memcpy(&pixel, bytes, sizeof(pixel));
return {Convert5To8((pixel >> 11) & 0x1F), Convert5To8((pixel >> 6) & 0x1F), return {Convert5To8((pixel >> 11) & 0x1F), Convert5To8((pixel >> 6) & 0x1F),
@ -108,7 +108,7 @@ inline Common::Vec4<u8> DecodeRGB5A1(const u8* bytes) {
* @param bytes Pointer to encoded source color * @param bytes Pointer to encoded source color
* @return Result color decoded as Common::Vec4<u8> * @return Result color decoded as Common::Vec4<u8>
*/ */
inline Common::Vec4<u8> DecodeRGBA4(const u8* bytes) { [[nodiscard]] inline Common::Vec4<u8> DecodeRGBA4(const u8* bytes) {
u16_le pixel; u16_le pixel;
std::memcpy(&pixel, bytes, sizeof(pixel)); std::memcpy(&pixel, bytes, sizeof(pixel));
return {Convert4To8((pixel >> 12) & 0xF), Convert4To8((pixel >> 8) & 0xF), return {Convert4To8((pixel >> 12) & 0xF), Convert4To8((pixel >> 8) & 0xF),
@ -120,7 +120,7 @@ inline Common::Vec4<u8> DecodeRGBA4(const u8* bytes) {
* @param bytes Pointer to encoded source value * @param bytes Pointer to encoded source value
* @return Depth value as an u32 * @return Depth value as an u32
*/ */
inline u32 DecodeD16(const u8* bytes) { [[nodiscard]] inline u32 DecodeD16(const u8* bytes) {
u16_le data; u16_le data;
std::memcpy(&data, bytes, sizeof(data)); std::memcpy(&data, bytes, sizeof(data));
return data; return data;
@ -131,7 +131,7 @@ inline u32 DecodeD16(const u8* bytes) {
* @param bytes Pointer to encoded source value * @param bytes Pointer to encoded source value
* @return Depth value as an u32 * @return Depth value as an u32
*/ */
inline u32 DecodeD24(const u8* bytes) { [[nodiscard]] inline u32 DecodeD24(const u8* bytes) {
return (bytes[2] << 16) | (bytes[1] << 8) | bytes[0]; return (bytes[2] << 16) | (bytes[1] << 8) | bytes[0];
} }
@ -140,7 +140,7 @@ inline u32 DecodeD24(const u8* bytes) {
* @param bytes Pointer to encoded source values * @param bytes Pointer to encoded source values
* @return Resulting values stored as a Common::Vec2 * @return Resulting values stored as a Common::Vec2
*/ */
inline Common::Vec2<u32> DecodeD24S8(const u8* bytes) { [[nodiscard]] inline Common::Vec2<u32> DecodeD24S8(const u8* bytes) {
return {static_cast<u32>((bytes[2] << 16) | (bytes[1] << 8) | bytes[0]), bytes[3]}; return {static_cast<u32>((bytes[2] << 16) | (bytes[1] << 8) | bytes[0]), bytes[3]};
} }

View file

@ -53,14 +53,14 @@ __declspec(dllimport) void __stdcall DebugBreak(void);
// Call directly after the command or use the error num. // Call directly after the command or use the error num.
// This function might change the error code. // This function might change the error code.
// Defined in Misc.cpp. // Defined in Misc.cpp.
std::string GetLastErrorMsg(); [[nodiscard]] std::string GetLastErrorMsg();
#define DECLARE_ENUM_FLAG_OPERATORS(type) \ #define DECLARE_ENUM_FLAG_OPERATORS(type) \
constexpr type operator|(type a, type b) noexcept { \ [[nodiscard]] constexpr type operator|(type a, type b) noexcept { \
using T = std::underlying_type_t<type>; \ using T = std::underlying_type_t<type>; \
return static_cast<type>(static_cast<T>(a) | static_cast<T>(b)); \ return static_cast<type>(static_cast<T>(a) | static_cast<T>(b)); \
} \ } \
constexpr type operator&(type a, type b) noexcept { \ [[nodiscard]] constexpr type operator&(type a, type b) noexcept { \
using T = std::underlying_type_t<type>; \ using T = std::underlying_type_t<type>; \
return static_cast<type>(static_cast<T>(a) & static_cast<T>(b)); \ return static_cast<type>(static_cast<T>(a) & static_cast<T>(b)); \
} \ } \
@ -74,22 +74,22 @@ std::string GetLastErrorMsg();
a = static_cast<type>(static_cast<T>(a) & static_cast<T>(b)); \ a = static_cast<type>(static_cast<T>(a) & static_cast<T>(b)); \
return a; \ return a; \
} \ } \
constexpr type operator~(type key) noexcept { \ [[nodiscard]] constexpr type operator~(type key) noexcept { \
using T = std::underlying_type_t<type>; \ using T = std::underlying_type_t<type>; \
return static_cast<type>(~static_cast<T>(key)); \ return static_cast<type>(~static_cast<T>(key)); \
} \ } \
constexpr bool True(type key) noexcept { \ [[nodiscard]] constexpr bool True(type key) noexcept { \
using T = std::underlying_type_t<type>; \ using T = std::underlying_type_t<type>; \
return static_cast<T>(key) != 0; \ return static_cast<T>(key) != 0; \
} \ } \
constexpr bool False(type key) noexcept { \ [[nodiscard]] constexpr bool False(type key) noexcept { \
using T = std::underlying_type_t<type>; \ using T = std::underlying_type_t<type>; \
return static_cast<T>(key) == 0; \ return static_cast<T>(key) == 0; \
} }
namespace Common { namespace Common {
constexpr u32 MakeMagic(char a, char b, char c, char d) { [[nodiscard]] constexpr u32 MakeMagic(char a, char b, char c, char d) {
return u32(a) | u32(b) << 8 | u32(c) << 16 | u32(d) << 24; return u32(a) | u32(b) << 8 | u32(c) << 16 | u32(d) << 24;
} }

View file

@ -33,7 +33,7 @@ public:
~DynamicLibrary(); ~DynamicLibrary();
/// Returns the specified library name with the platform-specific suffix added. /// Returns the specified library name with the platform-specific suffix added.
static std::string GetUnprefixedFilename(const char* filename); [[nodiscard]] static std::string GetUnprefixedFilename(const char* filename);
/// Returns the specified library name in platform-specific format. /// Returns the specified library name in platform-specific format.
/// Major/minor versions will not be included if set to -1. /// Major/minor versions will not be included if set to -1.
@ -41,28 +41,29 @@ public:
/// Windows: LIBNAME-MAJOR-MINOR.dll /// Windows: LIBNAME-MAJOR-MINOR.dll
/// Linux: libLIBNAME.so.MAJOR.MINOR /// Linux: libLIBNAME.so.MAJOR.MINOR
/// Mac: libLIBNAME.MAJOR.MINOR.dylib /// Mac: libLIBNAME.MAJOR.MINOR.dylib
static std::string GetVersionedFilename(const char* libname, int major = -1, int minor = -1); [[nodiscard]] static std::string GetVersionedFilename(const char* libname, int major = -1,
int minor = -1);
/// Returns true if a module is loaded, otherwise false. /// Returns true if a module is loaded, otherwise false.
bool IsOpen() const { [[nodiscard]] bool IsOpen() const {
return handle != nullptr; return handle != nullptr;
} }
/// Loads (or replaces) the handle with the specified library file name. /// Loads (or replaces) the handle with the specified library file name.
/// Returns true if the library was loaded and can be used. /// Returns true if the library was loaded and can be used.
bool Open(const char* filename); [[nodiscard]] bool Open(const char* filename);
/// Unloads the library, any function pointers from this library are no longer valid. /// Unloads the library, any function pointers from this library are no longer valid.
void Close(); void Close();
/// Returns the address of the specified symbol (function or variable) as an untyped pointer. /// Returns the address of the specified symbol (function or variable) as an untyped pointer.
/// If the specified symbol does not exist in this library, nullptr is returned. /// If the specified symbol does not exist in this library, nullptr is returned.
void* GetSymbolAddress(const char* name) const; [[nodiscard]] void* GetSymbolAddress(const char* name) const;
/// Obtains the address of the specified symbol, automatically casting to the correct type. /// Obtains the address of the specified symbol, automatically casting to the correct type.
/// Returns true if the symbol was found and assigned, otherwise false. /// Returns true if the symbol was found and assigned, otherwise false.
template <typename T> template <typename T>
bool GetSymbol(const char* name, T* ptr) const { [[nodiscard]] bool GetSymbol(const char* name, T* ptr) const {
*ptr = reinterpret_cast<T>(GetSymbolAddress(name)); *ptr = reinterpret_cast<T>(GetSymbolAddress(name));
return *ptr != nullptr; return *ptr != nullptr;
} }

View file

@ -47,7 +47,7 @@ public:
/// Yields control from Fiber 'from' to Fiber 'to' /// Yields control from Fiber 'from' to Fiber 'to'
/// Fiber 'from' must be the currently running fiber. /// Fiber 'from' must be the currently running fiber.
static void YieldTo(std::shared_ptr<Fiber>& from, std::shared_ptr<Fiber>& to); static void YieldTo(std::shared_ptr<Fiber>& from, std::shared_ptr<Fiber>& to);
static std::shared_ptr<Fiber> ThreadToFiber(); [[nodiscard]] static std::shared_ptr<Fiber> ThreadToFiber();
void SetRewindPoint(std::function<void(void*)>&& rewind_func, void* start_parameter); void SetRewindPoint(std::function<void(void*)>&& rewind_func, void* start_parameter);

View file

@ -48,19 +48,19 @@ struct FSTEntry {
}; };
// Returns true if file filename exists // Returns true if file filename exists
bool Exists(const std::string& filename); [[nodiscard]] bool Exists(const std::string& filename);
// Returns true if filename is a directory // Returns true if filename is a directory
bool IsDirectory(const std::string& filename); [[nodiscard]] bool IsDirectory(const std::string& filename);
// Returns the size of filename (64bit) // Returns the size of filename (64bit)
u64 GetSize(const std::string& filename); [[nodiscard]] u64 GetSize(const std::string& filename);
// Overloaded GetSize, accepts file descriptor // Overloaded GetSize, accepts file descriptor
u64 GetSize(const int fd); [[nodiscard]] u64 GetSize(int fd);
// Overloaded GetSize, accepts FILE* // Overloaded GetSize, accepts FILE*
u64 GetSize(FILE* f); [[nodiscard]] u64 GetSize(FILE* f);
// Returns true if successful, or path already exists. // Returns true if successful, or path already exists.
bool CreateDir(const std::string& filename); bool CreateDir(const std::string& filename);
@ -120,7 +120,7 @@ u64 ScanDirectoryTree(const std::string& directory, FSTEntry& parent_entry,
bool DeleteDirRecursively(const std::string& directory, unsigned int recursion = 256); bool DeleteDirRecursively(const std::string& directory, unsigned int recursion = 256);
// Returns the current directory // Returns the current directory
std::optional<std::string> GetCurrentDir(); [[nodiscard]] std::optional<std::string> GetCurrentDir();
// Create directory and copy contents (does not overwrite existing files) // Create directory and copy contents (does not overwrite existing files)
void CopyDir(const std::string& source_path, const std::string& dest_path); void CopyDir(const std::string& source_path, const std::string& dest_path);
@ -132,20 +132,20 @@ bool SetCurrentDir(const std::string& directory);
// directory. To be used in "multi-user" mode (that is, installed). // directory. To be used in "multi-user" mode (that is, installed).
const std::string& GetUserPath(UserPath path, const std::string& new_path = ""); const std::string& GetUserPath(UserPath path, const std::string& new_path = "");
std::string GetHactoolConfigurationPath(); [[nodiscard]] std::string GetHactoolConfigurationPath();
std::string GetNANDRegistrationDir(bool system = false); [[nodiscard]] std::string GetNANDRegistrationDir(bool system = false);
// Returns the path to where the sys file are // Returns the path to where the sys file are
std::string GetSysDirectory(); [[nodiscard]] std::string GetSysDirectory();
#ifdef __APPLE__ #ifdef __APPLE__
std::string GetBundleDirectory(); [[nodiscard]] std::string GetBundleDirectory();
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
const std::string& GetExeDirectory(); [[nodiscard]] const std::string& GetExeDirectory();
std::string AppDataRoamingDirectory(); [[nodiscard]] std::string AppDataRoamingDirectory();
#endif #endif
std::size_t WriteStringToFile(bool text_file, const std::string& filename, std::string_view str); std::size_t WriteStringToFile(bool text_file, const std::string& filename, std::string_view str);
@ -164,37 +164,44 @@ void SplitFilename83(const std::string& filename, std::array<char, 9>& short_nam
// Splits the path on '/' or '\' and put the components into a vector // Splits the path on '/' or '\' and put the components into a vector
// i.e. "C:\Users\Yuzu\Documents\save.bin" becomes {"C:", "Users", "Yuzu", "Documents", "save.bin" } // i.e. "C:\Users\Yuzu\Documents\save.bin" becomes {"C:", "Users", "Yuzu", "Documents", "save.bin" }
std::vector<std::string> SplitPathComponents(std::string_view filename); [[nodiscard]] std::vector<std::string> SplitPathComponents(std::string_view filename);
// Gets all of the text up to the last '/' or '\' in the path. // Gets all of the text up to the last '/' or '\' in the path.
std::string_view GetParentPath(std::string_view path); [[nodiscard]] std::string_view GetParentPath(std::string_view path);
// Gets all of the text after the first '/' or '\' in the path. // Gets all of the text after the first '/' or '\' in the path.
std::string_view GetPathWithoutTop(std::string_view path); [[nodiscard]] std::string_view GetPathWithoutTop(std::string_view path);
// Gets the filename of the path // Gets the filename of the path
std::string_view GetFilename(std::string_view path); [[nodiscard]] std::string_view GetFilename(std::string_view path);
// Gets the extension of the filename // Gets the extension of the filename
std::string_view GetExtensionFromFilename(std::string_view name); [[nodiscard]] std::string_view GetExtensionFromFilename(std::string_view name);
// Removes the final '/' or '\' if one exists // Removes the final '/' or '\' if one exists
std::string_view RemoveTrailingSlash(std::string_view path); [[nodiscard]] std::string_view RemoveTrailingSlash(std::string_view path);
// Creates a new vector containing indices [first, last) from the original. // Creates a new vector containing indices [first, last) from the original.
template <typename T> template <typename T>
std::vector<T> SliceVector(const std::vector<T>& vector, std::size_t first, std::size_t last) { [[nodiscard]] std::vector<T> SliceVector(const std::vector<T>& vector, std::size_t first,
if (first >= last) std::size_t last) {
if (first >= last) {
return {}; return {};
}
last = std::min<std::size_t>(last, vector.size()); last = std::min<std::size_t>(last, vector.size());
return std::vector<T>(vector.begin() + first, vector.begin() + first + last); return std::vector<T>(vector.begin() + first, vector.begin() + first + last);
} }
enum class DirectorySeparator { ForwardSlash, BackwardSlash, PlatformDefault }; enum class DirectorySeparator {
ForwardSlash,
BackwardSlash,
PlatformDefault,
};
// Removes trailing slash, makes all '\\' into '/', and removes duplicate '/'. Makes '/' into '\\' // Removes trailing slash, makes all '\\' into '/', and removes duplicate '/'. Makes '/' into '\\'
// depending if directory_separator is BackwardSlash or PlatformDefault and running on windows // depending if directory_separator is BackwardSlash or PlatformDefault and running on windows
std::string SanitizePath(std::string_view path, [[nodiscard]] std::string SanitizePath(
std::string_view path,
DirectorySeparator directory_separator = DirectorySeparator::ForwardSlash); DirectorySeparator directory_separator = DirectorySeparator::ForwardSlash);
// simple wrapper for cstdlib file functions to // simple wrapper for cstdlib file functions to
@ -215,7 +222,7 @@ public:
void Swap(IOFile& other) noexcept; void Swap(IOFile& other) noexcept;
bool Open(const std::string& filename, const char openmode[], int flags = 0); [[nodiscard]] bool Open(const std::string& filename, const char openmode[], int flags = 0);
bool Close(); bool Close();
template <typename T> template <typename T>
@ -256,13 +263,13 @@ public:
return WriteArray(str.data(), str.length()); return WriteArray(str.data(), str.length());
} }
bool IsOpen() const { [[nodiscard]] bool IsOpen() const {
return nullptr != m_file; return nullptr != m_file;
} }
bool Seek(s64 off, int origin) const; bool Seek(s64 off, int origin) const;
u64 Tell() const; [[nodiscard]] u64 Tell() const;
u64 GetSize() const; [[nodiscard]] u64 GetSize() const;
bool Resize(u64 size); bool Resize(u64 size);
bool Flush(); bool Flush();

View file

@ -5,36 +5,11 @@
#pragma once #pragma once
#include <cstddef> #include <cstddef>
#include <cstring>
#include <utility> #include <utility>
#include <boost/functional/hash.hpp> #include <boost/functional/hash.hpp>
#include "common/cityhash.h"
#include "common/common_types.h"
namespace Common { namespace Common {
/**
* Computes a 64-bit hash over the specified block of data
* @param data Block of data to compute hash over
* @param len Length of data (in bytes) to compute hash over
* @returns 64-bit hash value that was computed over the data block
*/
static inline u64 ComputeHash64(const void* data, std::size_t len) {
return CityHash64(static_cast<const char*>(data), len);
}
/**
* Computes a 64-bit hash of a struct. In addition to being trivially copyable, it is also critical
* that either the struct includes no padding, or that any padding is initialized to a known value
* by memsetting the struct to 0 before filling it in.
*/
template <typename T>
static inline u64 ComputeStructHash64(const T& data) {
static_assert(std::is_trivially_copyable_v<T>,
"Type passed to ComputeStructHash64 must be trivially copyable");
return ComputeHash64(&data, sizeof(data));
}
struct PairHash { struct PairHash {
template <class T1, class T2> template <class T1, class T2>
std::size_t operator()(const std::pair<T1, T2>& pair) const noexcept { std::size_t operator()(const std::pair<T1, T2>& pair) const noexcept {

View file

@ -14,7 +14,7 @@
namespace Common { namespace Common {
constexpr u8 ToHexNibble(char c) { [[nodiscard]] constexpr u8 ToHexNibble(char c) {
if (c >= 65 && c <= 70) { if (c >= 65 && c <= 70) {
return c - 55; return c - 55;
} }
@ -26,10 +26,10 @@ constexpr u8 ToHexNibble(char c) {
return c - 48; return c - 48;
} }
std::vector<u8> HexStringToVector(std::string_view str, bool little_endian); [[nodiscard]] std::vector<u8> HexStringToVector(std::string_view str, bool little_endian);
template <std::size_t Size, bool le = false> template <std::size_t Size, bool le = false>
constexpr std::array<u8, Size> HexStringToArray(std::string_view str) { [[nodiscard]] constexpr std::array<u8, Size> HexStringToArray(std::string_view str) {
std::array<u8, Size> out{}; std::array<u8, Size> out{};
if constexpr (le) { if constexpr (le) {
for (std::size_t i = 2 * Size - 2; i <= 2 * Size; i -= 2) { for (std::size_t i = 2 * Size - 2; i <= 2 * Size; i -= 2) {
@ -44,7 +44,7 @@ constexpr std::array<u8, Size> HexStringToArray(std::string_view str) {
} }
template <typename ContiguousContainer> template <typename ContiguousContainer>
std::string HexToString(const ContiguousContainer& data, bool upper = true) { [[nodiscard]] std::string HexToString(const ContiguousContainer& data, bool upper = true) {
static_assert(std::is_same_v<typename ContiguousContainer::value_type, u8>, static_assert(std::is_same_v<typename ContiguousContainer::value_type, u8>,
"Underlying type within the contiguous container must be u8."); "Underlying type within the contiguous container must be u8.");
@ -60,11 +60,11 @@ std::string HexToString(const ContiguousContainer& data, bool upper = true) {
return out; return out;
} }
constexpr std::array<u8, 16> AsArray(const char (&data)[17]) { [[nodiscard]] constexpr std::array<u8, 16> AsArray(const char (&data)[17]) {
return HexStringToArray<16>(data); return HexStringToArray<16>(data);
} }
constexpr std::array<u8, 32> AsArray(const char (&data)[65]) { [[nodiscard]] constexpr std::array<u8, 32> AsArray(const char (&data)[65]) {
return HexStringToArray<32>(data); return HexStringToArray<32>(data);
} }

View file

@ -18,7 +18,7 @@ namespace Common::Compression {
* *
* @return the compressed data. * @return the compressed data.
*/ */
std::vector<u8> CompressDataLZ4(std::span<const u8> source); [[nodiscard]] std::vector<u8> CompressDataLZ4(std::span<const u8> source);
/** /**
* Utilizes the LZ4 subalgorithm LZ4HC with the specified compression level. Higher compression * Utilizes the LZ4 subalgorithm LZ4HC with the specified compression level. Higher compression
@ -31,7 +31,7 @@ std::vector<u8> CompressDataLZ4(std::span<const u8> source);
* *
* @return the compressed data. * @return the compressed data.
*/ */
std::vector<u8> CompressDataLZ4HC(std::span<const u8> source, s32 compression_level); [[nodiscard]] std::vector<u8> CompressDataLZ4HC(std::span<const u8> source, s32 compression_level);
/** /**
* Utilizes the LZ4 subalgorithm LZ4HC with the highest possible compression level. * Utilizes the LZ4 subalgorithm LZ4HC with the highest possible compression level.
@ -40,7 +40,7 @@ std::vector<u8> CompressDataLZ4HC(std::span<const u8> source, s32 compression_le
* *
* @return the compressed data. * @return the compressed data.
*/ */
std::vector<u8> CompressDataLZ4HCMax(std::span<const u8> source); [[nodiscard]] std::vector<u8> CompressDataLZ4HCMax(std::span<const u8> source);
/** /**
* Decompresses a source memory region with LZ4 and returns the uncompressed data in a vector. * Decompresses a source memory region with LZ4 and returns the uncompressed data in a vector.
@ -50,6 +50,7 @@ std::vector<u8> CompressDataLZ4HCMax(std::span<const u8> source);
* *
* @return the decompressed data. * @return the decompressed data.
*/ */
std::vector<u8> DecompressDataLZ4(const std::vector<u8>& compressed, std::size_t uncompressed_size); [[nodiscard]] std::vector<u8> DecompressDataLZ4(const std::vector<u8>& compressed,
std::size_t uncompressed_size);
} // namespace Common::Compression } // namespace Common::Compression

View file

@ -23,7 +23,7 @@ struct Rectangle {
constexpr Rectangle(T left, T top, T right, T bottom) constexpr Rectangle(T left, T top, T right, T bottom)
: left(left), top(top), right(right), bottom(bottom) {} : left(left), top(top), right(right), bottom(bottom) {}
T GetWidth() const { [[nodiscard]] T GetWidth() const {
if constexpr (std::is_floating_point_v<T>) { if constexpr (std::is_floating_point_v<T>) {
return std::abs(right - left); return std::abs(right - left);
} else { } else {
@ -31,7 +31,7 @@ struct Rectangle {
} }
} }
T GetHeight() const { [[nodiscard]] T GetHeight() const {
if constexpr (std::is_floating_point_v<T>) { if constexpr (std::is_floating_point_v<T>) {
return std::abs(bottom - top); return std::abs(bottom - top);
} else { } else {
@ -39,15 +39,15 @@ struct Rectangle {
} }
} }
Rectangle<T> TranslateX(const T x) const { [[nodiscard]] Rectangle<T> TranslateX(const T x) const {
return Rectangle{left + x, top, right + x, bottom}; return Rectangle{left + x, top, right + x, bottom};
} }
Rectangle<T> TranslateY(const T y) const { [[nodiscard]] Rectangle<T> TranslateY(const T y) const {
return Rectangle{left, top + y, right, bottom + y}; return Rectangle{left, top + y, right, bottom + y};
} }
Rectangle<T> Scale(const float s) const { [[nodiscard]] Rectangle<T> Scale(const float s) const {
return Rectangle{left, top, static_cast<T>(left + GetWidth() * s), return Rectangle{left, top, static_cast<T>(left + GetWidth() * s),
static_cast<T>(top + GetHeight() * s)}; static_cast<T>(top + GetHeight() * s)};
} }

View file

@ -17,6 +17,6 @@ struct MemoryInfo {
* Gets the memory info of the host system * Gets the memory info of the host system
* @return Reference to a MemoryInfo struct with the physical and swap memory sizes in bytes * @return Reference to a MemoryInfo struct with the physical and swap memory sizes in bytes
*/ */
const MemoryInfo& GetMemInfo(); [[nodiscard]] const MemoryInfo& GetMemInfo();
} // namespace Common } // namespace Common

View file

@ -223,15 +223,15 @@ public:
ListShiftForward(levels[priority], n); ListShiftForward(levels[priority], n);
} }
std::size_t depth() const { [[nodiscard]] std::size_t depth() const {
return Depth; return Depth;
} }
std::size_t size(u32 priority) const { [[nodiscard]] std::size_t size(u32 priority) const {
return levels[priority].size(); return levels[priority].size();
} }
std::size_t size() const { [[nodiscard]] std::size_t size() const {
u64 priorities = used_priorities; u64 priorities = used_priorities;
std::size_t size = 0; std::size_t size = 0;
while (priorities != 0) { while (priorities != 0) {
@ -242,64 +242,64 @@ public:
return size; return size;
} }
bool empty() const { [[nodiscard]] bool empty() const {
return used_priorities == 0; return used_priorities == 0;
} }
bool empty(u32 priority) const { [[nodiscard]] bool empty(u32 priority) const {
return (used_priorities & (1ULL << priority)) == 0; return (used_priorities & (1ULL << priority)) == 0;
} }
u32 highest_priority_set(u32 max_priority = 0) const { [[nodiscard]] u32 highest_priority_set(u32 max_priority = 0) const {
const u64 priorities = const u64 priorities =
max_priority == 0 ? used_priorities : (used_priorities & ~((1ULL << max_priority) - 1)); max_priority == 0 ? used_priorities : (used_priorities & ~((1ULL << max_priority) - 1));
return priorities == 0 ? Depth : static_cast<u32>(CountTrailingZeroes64(priorities)); return priorities == 0 ? Depth : static_cast<u32>(CountTrailingZeroes64(priorities));
} }
u32 lowest_priority_set(u32 min_priority = Depth - 1) const { [[nodiscard]] u32 lowest_priority_set(u32 min_priority = Depth - 1) const {
const u64 priorities = min_priority >= Depth - 1 const u64 priorities = min_priority >= Depth - 1
? used_priorities ? used_priorities
: (used_priorities & ((1ULL << (min_priority + 1)) - 1)); : (used_priorities & ((1ULL << (min_priority + 1)) - 1));
return priorities == 0 ? Depth : 63 - CountLeadingZeroes64(priorities); return priorities == 0 ? Depth : 63 - CountLeadingZeroes64(priorities);
} }
const_iterator cbegin(u32 max_prio = 0) const { [[nodiscard]] const_iterator cbegin(u32 max_prio = 0) const {
const u32 priority = highest_priority_set(max_prio); const u32 priority = highest_priority_set(max_prio);
return priority == Depth ? cend() return priority == Depth ? cend()
: const_iterator{*this, levels[priority].cbegin(), priority}; : const_iterator{*this, levels[priority].cbegin(), priority};
} }
const_iterator begin(u32 max_prio = 0) const { [[nodiscard]] const_iterator begin(u32 max_prio = 0) const {
return cbegin(max_prio); return cbegin(max_prio);
} }
iterator begin(u32 max_prio = 0) { [[nodiscard]] iterator begin(u32 max_prio = 0) {
const u32 priority = highest_priority_set(max_prio); const u32 priority = highest_priority_set(max_prio);
return priority == Depth ? end() : iterator{*this, levels[priority].begin(), priority}; return priority == Depth ? end() : iterator{*this, levels[priority].begin(), priority};
} }
const_iterator cend(u32 min_prio = Depth - 1) const { [[nodiscard]] const_iterator cend(u32 min_prio = Depth - 1) const {
return min_prio == Depth - 1 ? const_iterator{*this, Depth} : cbegin(min_prio + 1); return min_prio == Depth - 1 ? const_iterator{*this, Depth} : cbegin(min_prio + 1);
} }
const_iterator end(u32 min_prio = Depth - 1) const { [[nodiscard]] const_iterator end(u32 min_prio = Depth - 1) const {
return cend(min_prio); return cend(min_prio);
} }
iterator end(u32 min_prio = Depth - 1) { [[nodiscard]] iterator end(u32 min_prio = Depth - 1) {
return min_prio == Depth - 1 ? iterator{*this, Depth} : begin(min_prio + 1); return min_prio == Depth - 1 ? iterator{*this, Depth} : begin(min_prio + 1);
} }
T& front(u32 max_priority = 0) { [[nodiscard]] T& front(u32 max_priority = 0) {
const u32 priority = highest_priority_set(max_priority); const u32 priority = highest_priority_set(max_priority);
return levels[priority == Depth ? 0 : priority].front(); return levels[priority == Depth ? 0 : priority].front();
} }
const T& front(u32 max_priority = 0) const { [[nodiscard]] const T& front(u32 max_priority = 0) const {
const u32 priority = highest_priority_set(max_priority); const u32 priority = highest_priority_set(max_priority);
return levels[priority == Depth ? 0 : priority].front(); return levels[priority == Depth ? 0 : priority].front();
} }
T back(u32 min_priority = Depth - 1) { [[nodiscard]] T& back(u32 min_priority = Depth - 1) {
const u32 priority = lowest_priority_set(min_priority); // intended const u32 priority = lowest_priority_set(min_priority); // intended
return levels[priority == Depth ? 63 : priority].back(); return levels[priority == Depth ? 63 : priority].back();
} }
const T& back(u32 min_priority = Depth - 1) const { [[nodiscard]] const T& back(u32 min_priority = Depth - 1) const {
const u32 priority = lowest_priority_set(min_priority); // intended const u32 priority = lowest_priority_set(min_priority); // intended
return levels[priority == Depth ? 63 : priority].back(); return levels[priority == Depth ? 63 : priority].back();
} }
@ -329,7 +329,8 @@ private:
in_list.splice(position, out_list, element); in_list.splice(position, out_list, element);
} }
static const_list_iterator ListIterateTo(const std::list<T>& list, const T& element) { [[nodiscard]] static const_list_iterator ListIterateTo(const std::list<T>& list,
const T& element) {
auto it = list.cbegin(); auto it = list.cbegin();
while (it != list.cend() && *it != element) { while (it != list.cend() && *it != element) {
++it; ++it;

View file

@ -36,11 +36,11 @@ struct SpecialRegion {
MemoryHookPointer handler; MemoryHookPointer handler;
bool operator<(const SpecialRegion& other) const { [[nodiscard]] bool operator<(const SpecialRegion& other) const {
return std::tie(type, handler) < std::tie(other.type, other.handler); return std::tie(type, handler) < std::tie(other.type, other.handler);
} }
bool operator==(const SpecialRegion& other) const { [[nodiscard]] bool operator==(const SpecialRegion& other) const {
return std::tie(type, handler) == std::tie(other.type, other.handler); return std::tie(type, handler) == std::tie(other.type, other.handler);
} }
}; };

View file

@ -24,14 +24,14 @@ public:
ParamPackage& operator=(const ParamPackage& other) = default; ParamPackage& operator=(const ParamPackage& other) = default;
ParamPackage& operator=(ParamPackage&& other) = default; ParamPackage& operator=(ParamPackage&& other) = default;
std::string Serialize() const; [[nodiscard]] std::string Serialize() const;
std::string Get(const std::string& key, const std::string& default_value) const; [[nodiscard]] std::string Get(const std::string& key, const std::string& default_value) const;
int Get(const std::string& key, int default_value) const; [[nodiscard]] int Get(const std::string& key, int default_value) const;
float Get(const std::string& key, float default_value) const; [[nodiscard]] float Get(const std::string& key, float default_value) const;
void Set(const std::string& key, std::string value); void Set(const std::string& key, std::string value);
void Set(const std::string& key, int value); void Set(const std::string& key, int value);
void Set(const std::string& key, float value); void Set(const std::string& key, float value);
bool Has(const std::string& key) const; [[nodiscard]] bool Has(const std::string& key) const;
void Erase(const std::string& key); void Erase(const std::string& key);
void Clear(); void Clear();

View file

@ -14,35 +14,36 @@ public:
Vec3<T> xyz; Vec3<T> xyz;
T w{}; T w{};
Quaternion<decltype(-T{})> Inverse() const { [[nodiscard]] Quaternion<decltype(-T{})> Inverse() const {
return {-xyz, w}; return {-xyz, w};
} }
Quaternion<decltype(T{} + T{})> operator+(const Quaternion& other) const { [[nodiscard]] Quaternion<decltype(T{} + T{})> operator+(const Quaternion& other) const {
return {xyz + other.xyz, w + other.w}; return {xyz + other.xyz, w + other.w};
} }
Quaternion<decltype(T{} - T{})> operator-(const Quaternion& other) const { [[nodiscard]] Quaternion<decltype(T{} - T{})> operator-(const Quaternion& other) const {
return {xyz - other.xyz, w - other.w}; return {xyz - other.xyz, w - other.w};
} }
Quaternion<decltype(T{} * T{} - T{} * T{})> operator*(const Quaternion& other) const { [[nodiscard]] Quaternion<decltype(T{} * T{} - T{} * T{})> operator*(
const Quaternion& other) const {
return {xyz * other.w + other.xyz * w + Cross(xyz, other.xyz), return {xyz * other.w + other.xyz * w + Cross(xyz, other.xyz),
w * other.w - Dot(xyz, other.xyz)}; w * other.w - Dot(xyz, other.xyz)};
} }
Quaternion<T> Normalized() const { [[nodiscard]] Quaternion<T> Normalized() const {
T length = std::sqrt(xyz.Length2() + w * w); T length = std::sqrt(xyz.Length2() + w * w);
return {xyz / length, w / length}; return {xyz / length, w / length};
} }
}; };
template <typename T> template <typename T>
auto QuaternionRotate(const Quaternion<T>& q, const Vec3<T>& v) { [[nodiscard]] auto QuaternionRotate(const Quaternion<T>& q, const Vec3<T>& v) {
return v + 2 * Cross(q.xyz, Cross(q.xyz, v) + v * q.w); return v + 2 * Cross(q.xyz, Cross(q.xyz, v) + v * q.w);
} }
inline Quaternion<float> MakeQuaternion(const Vec3<float>& axis, float angle) { [[nodiscard]] inline Quaternion<float> MakeQuaternion(const Vec3<float>& axis, float angle) {
return {axis * std::sin(angle / 2), std::cos(angle / 2)}; return {axis * std::sin(angle / 2), std::cos(angle / 2)};
} }

View file

@ -91,12 +91,12 @@ public:
} }
/// @returns Number of slots used /// @returns Number of slots used
std::size_t Size() const { [[nodiscard]] std::size_t Size() const {
return m_write_index.load() - m_read_index.load(); return m_write_index.load() - m_read_index.load();
} }
/// @returns Maximum size of ring buffer /// @returns Maximum size of ring buffer
constexpr std::size_t Capacity() const { [[nodiscard]] constexpr std::size_t Capacity() const {
return capacity; return capacity;
} }

View file

@ -17,7 +17,7 @@ class SpinLock {
public: public:
void lock(); void lock();
void unlock(); void unlock();
bool try_lock(); [[nodiscard]] bool try_lock();
private: private:
std::atomic_flag lck = ATOMIC_FLAG_INIT; std::atomic_flag lck = ATOMIC_FLAG_INIT;

View file

@ -12,19 +12,19 @@
namespace Common { namespace Common {
/// Make a string lowercase /// Make a string lowercase
std::string ToLower(std::string str); [[nodiscard]] std::string ToLower(std::string str);
/// Make a string uppercase /// Make a string uppercase
std::string ToUpper(std::string str); [[nodiscard]] std::string ToUpper(std::string str);
std::string StringFromBuffer(const std::vector<u8>& data); [[nodiscard]] std::string StringFromBuffer(const std::vector<u8>& data);
std::string StripSpaces(const std::string& s); [[nodiscard]] std::string StripSpaces(const std::string& s);
std::string StripQuotes(const std::string& s); [[nodiscard]] std::string StripQuotes(const std::string& s);
std::string StringFromBool(bool value); [[nodiscard]] std::string StringFromBool(bool value);
std::string TabsToSpaces(int tab_size, std::string in); [[nodiscard]] std::string TabsToSpaces(int tab_size, std::string in);
void SplitString(const std::string& str, char delim, std::vector<std::string>& output); void SplitString(const std::string& str, char delim, std::vector<std::string>& output);
@ -34,14 +34,15 @@ bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _
void BuildCompleteFilename(std::string& _CompleteFilename, const std::string& _Path, void BuildCompleteFilename(std::string& _CompleteFilename, const std::string& _Path,
const std::string& _Filename); const std::string& _Filename);
std::string ReplaceAll(std::string result, const std::string& src, const std::string& dest); [[nodiscard]] std::string ReplaceAll(std::string result, const std::string& src,
const std::string& dest);
std::string UTF16ToUTF8(const std::u16string& input); [[nodiscard]] std::string UTF16ToUTF8(const std::u16string& input);
std::u16string UTF8ToUTF16(const std::string& input); [[nodiscard]] std::u16string UTF8ToUTF16(const std::string& input);
#ifdef _WIN32 #ifdef _WIN32
std::string UTF16ToUTF8(const std::wstring& input); [[nodiscard]] std::string UTF16ToUTF8(const std::wstring& input);
std::wstring UTF8ToUTF16W(const std::string& str); [[nodiscard]] std::wstring UTF8ToUTF16W(const std::string& str);
#endif #endif
@ -50,7 +51,7 @@ std::wstring UTF8ToUTF16W(const std::string& str);
* `other` for equality. * `other` for equality.
*/ */
template <typename InIt> template <typename InIt>
bool ComparePartialString(InIt begin, InIt end, const char* other) { [[nodiscard]] bool ComparePartialString(InIt begin, InIt end, const char* other) {
for (; begin != end && *other != '\0'; ++begin, ++other) { for (; begin != end && *other != '\0'; ++begin, ++other) {
if (*begin != *other) { if (*begin != *other) {
return false; return false;
@ -64,14 +65,15 @@ bool ComparePartialString(InIt begin, InIt end, const char* other) {
* Creates a std::string from a fixed-size NUL-terminated char buffer. If the buffer isn't * Creates a std::string from a fixed-size NUL-terminated char buffer. If the buffer isn't
* NUL-terminated then the string ends at max_len characters. * NUL-terminated then the string ends at max_len characters.
*/ */
std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, std::size_t max_len); [[nodiscard]] std::string StringFromFixedZeroTerminatedBuffer(const char* buffer,
std::size_t max_len);
/** /**
* Creates a UTF-16 std::u16string from a fixed-size NUL-terminated char buffer. If the buffer isn't * Creates a UTF-16 std::u16string from a fixed-size NUL-terminated char buffer. If the buffer isn't
* null-terminated, then the string ends at the greatest multiple of two less then or equal to * null-terminated, then the string ends at the greatest multiple of two less then or equal to
* max_len_bytes. * max_len_bytes.
*/ */
std::u16string UTF16StringFromFixedZeroTerminatedBuffer(std::u16string_view buffer, [[nodiscard]] std::u16string UTF16StringFromFixedZeroTerminatedBuffer(std::u16string_view buffer,
std::size_t max_len); std::size_t max_len);
} // namespace Common } // namespace Common

View file

@ -63,30 +63,30 @@ public:
void Accept(VisitorInterface& visitor) const override; void Accept(VisitorInterface& visitor) const override;
const std::string& GetName() const override { [[nodiscard]] const std::string& GetName() const override {
return name; return name;
} }
/** /**
* Returns the type of the field. * Returns the type of the field.
*/ */
FieldType GetType() const { [[nodiscard]] FieldType GetType() const {
return type; return type;
} }
/** /**
* Returns the value of the field. * Returns the value of the field.
*/ */
const T& GetValue() const { [[nodiscard]] const T& GetValue() const {
return value; return value;
} }
bool operator==(const Field& other) const { [[nodiscard]] bool operator==(const Field& other) const {
return (type == other.type) && (name == other.name) && (value == other.value); return (type == other.type) && (name == other.name) && (value == other.value);
} }
bool operator!=(const Field& other) const { [[nodiscard]] bool operator!=(const Field& other) const {
return !(*this == other); return !operator==(other);
} }
private: private:

View file

@ -18,14 +18,14 @@ struct ThreadQueueList {
using Priority = unsigned int; using Priority = unsigned int;
// Number of priority levels. (Valid levels are [0..NUM_QUEUES).) // Number of priority levels. (Valid levels are [0..NUM_QUEUES).)
static const Priority NUM_QUEUES = N; static constexpr Priority NUM_QUEUES = N;
ThreadQueueList() { ThreadQueueList() {
first = nullptr; first = nullptr;
} }
// Only for debugging, returns priority level. // Only for debugging, returns priority level.
Priority contains(const T& uid) const { [[nodiscard]] Priority contains(const T& uid) const {
for (Priority i = 0; i < NUM_QUEUES; ++i) { for (Priority i = 0; i < NUM_QUEUES; ++i) {
const Queue& cur = queues[i]; const Queue& cur = queues[i];
if (std::find(cur.data.cbegin(), cur.data.cend(), uid) != cur.data.cend()) { if (std::find(cur.data.cbegin(), cur.data.cend(), uid) != cur.data.cend()) {
@ -36,7 +36,7 @@ struct ThreadQueueList {
return -1; return -1;
} }
T get_first() const { [[nodiscard]] T get_first() const {
const Queue* cur = first; const Queue* cur = first;
while (cur != nullptr) { while (cur != nullptr) {
if (!cur->data.empty()) { if (!cur->data.empty()) {
@ -49,7 +49,7 @@ struct ThreadQueueList {
} }
template <typename UnaryPredicate> template <typename UnaryPredicate>
T get_first_filter(UnaryPredicate filter) const { [[nodiscard]] T get_first_filter(UnaryPredicate filter) const {
const Queue* cur = first; const Queue* cur = first;
while (cur != nullptr) { while (cur != nullptr) {
if (!cur->data.empty()) { if (!cur->data.empty()) {
@ -129,7 +129,7 @@ struct ThreadQueueList {
first = nullptr; first = nullptr;
} }
bool empty(Priority priority) const { [[nodiscard]] bool empty(Priority priority) const {
const Queue* cur = &queues[priority]; const Queue* cur = &queues[priority];
return cur->data.empty(); return cur->data.empty();
} }

View file

@ -25,15 +25,15 @@ public:
delete read_ptr; delete read_ptr;
} }
std::size_t Size() const { [[nodiscard]] std::size_t Size() const {
return size.load(); return size.load();
} }
bool Empty() const { [[nodiscard]] bool Empty() const {
return Size() == 0; return Size() == 0;
} }
T& Front() const { [[nodiscard]] T& Front() const {
return read_ptr->current; return read_ptr->current;
} }
@ -130,15 +130,15 @@ private:
template <typename T> template <typename T>
class MPSCQueue { class MPSCQueue {
public: public:
std::size_t Size() const { [[nodiscard]] std::size_t Size() const {
return spsc_queue.Size(); return spsc_queue.Size();
} }
bool Empty() const { [[nodiscard]] bool Empty() const {
return spsc_queue.Empty(); return spsc_queue.Empty();
} }
T& Front() const { [[nodiscard]] T& Front() const {
return spsc_queue.Front(); return spsc_queue.Front();
} }

View file

@ -10,9 +10,9 @@
namespace Common::TimeZone { namespace Common::TimeZone {
/// Gets the default timezone, i.e. "GMT" /// Gets the default timezone, i.e. "GMT"
std::string GetDefaultTimeZone(); [[nodiscard]] std::string GetDefaultTimeZone();
/// Gets the offset of the current timezone (from the default), in seconds /// Gets the offset of the current timezone (from the default), in seconds
std::chrono::seconds GetCurrentOffsetSeconds(); [[nodiscard]] std::chrono::seconds GetCurrentOffsetSeconds();
} // namespace Common::TimeZone } // namespace Common::TimeZone

View file

@ -19,18 +19,18 @@ public:
// The time difference is always returned in milliseconds, regardless of alternative internal // The time difference is always returned in milliseconds, regardless of alternative internal
// representation // representation
std::chrono::milliseconds GetTimeDifference(); [[nodiscard]] std::chrono::milliseconds GetTimeDifference();
void AddTimeDifference(); void AddTimeDifference();
static std::chrono::seconds GetTimeSinceJan1970(); [[nodiscard]] static std::chrono::seconds GetTimeSinceJan1970();
static std::chrono::seconds GetLocalTimeSinceJan1970(); [[nodiscard]] static std::chrono::seconds GetLocalTimeSinceJan1970();
static double GetDoubleTime(); [[nodiscard]] static double GetDoubleTime();
static std::string GetTimeFormatted(); [[nodiscard]] static std::string GetTimeFormatted();
std::string GetTimeElapsedFormatted() const; [[nodiscard]] std::string GetTimeElapsedFormatted() const;
std::chrono::milliseconds GetTimeElapsed(); [[nodiscard]] std::chrono::milliseconds GetTimeElapsed();
static std::chrono::milliseconds GetTimeMs(); [[nodiscard]] static std::chrono::milliseconds GetTimeMs();
private: private:
std::chrono::milliseconds m_LastTime; std::chrono::milliseconds m_LastTime;

View file

@ -10,13 +10,13 @@
namespace Common { namespace Common {
// This function multiplies 2 u64 values and divides it by a u64 value. // This function multiplies 2 u64 values and divides it by a u64 value.
u64 MultiplyAndDivide64(u64 a, u64 b, u64 d); [[nodiscard]] u64 MultiplyAndDivide64(u64 a, u64 b, u64 d);
// This function multiplies 2 u64 values and produces a u128 value; // This function multiplies 2 u64 values and produces a u128 value;
u128 Multiply64Into128(u64 a, u64 b); [[nodiscard]] u128 Multiply64Into128(u64 a, u64 b);
// This function divides a u128 by a u32 value and produces two u64 values: // This function divides a u128 by a u32 value and produces two u64 values:
// the result of division and the remainder // the result of division and the remainder
std::pair<u64, u64> Divide128On32(u128 dividend, u32 divisor); [[nodiscard]] std::pair<u64, u64> Divide128On32(u128 dividend, u32 divisor);
} // namespace Common } // namespace Common

View file

@ -19,21 +19,21 @@ struct UUID {
constexpr explicit UUID(const u128& id) : uuid{id} {} constexpr explicit UUID(const u128& id) : uuid{id} {}
constexpr explicit UUID(const u64 lo, const u64 hi) : uuid{{lo, hi}} {} constexpr explicit UUID(const u64 lo, const u64 hi) : uuid{{lo, hi}} {}
constexpr explicit operator bool() const { [[nodiscard]] constexpr explicit operator bool() const {
return uuid[0] != INVALID_UUID[0] && uuid[1] != INVALID_UUID[1]; return uuid[0] != INVALID_UUID[0] && uuid[1] != INVALID_UUID[1];
} }
constexpr bool operator==(const UUID& rhs) const { [[nodiscard]] constexpr bool operator==(const UUID& rhs) const {
// TODO(DarkLordZach): Replace with uuid == rhs.uuid with C++20 // TODO(DarkLordZach): Replace with uuid == rhs.uuid with C++20
return uuid[0] == rhs.uuid[0] && uuid[1] == rhs.uuid[1]; return uuid[0] == rhs.uuid[0] && uuid[1] == rhs.uuid[1];
} }
constexpr bool operator!=(const UUID& rhs) const { [[nodiscard]] constexpr bool operator!=(const UUID& rhs) const {
return !operator==(rhs); return !operator==(rhs);
} }
// TODO(ogniK): Properly generate uuids based on RFC-4122 // TODO(ogniK): Properly generate uuids based on RFC-4122
static UUID Generate(); [[nodiscard]] static UUID Generate();
// Set the UUID to {0,0} to be considered an invalid user // Set the UUID to {0,0} to be considered an invalid user
constexpr void Invalidate() { constexpr void Invalidate() {
@ -41,12 +41,12 @@ struct UUID {
} }
// TODO(ogniK): Properly generate a Nintendo ID // TODO(ogniK): Properly generate a Nintendo ID
constexpr u64 GetNintendoID() const { [[nodiscard]] constexpr u64 GetNintendoID() const {
return uuid[0]; return uuid[0];
} }
std::string Format() const; [[nodiscard]] std::string Format() const;
std::string FormatSwitch() const; [[nodiscard]] std::string FormatSwitch() const;
}; };
static_assert(sizeof(UUID) == 16, "UUID is an invalid size!"); static_assert(sizeof(UUID) == 16, "UUID is an invalid size!");

View file

@ -52,15 +52,15 @@ public:
constexpr Vec2(const T& x_, const T& y_) : x(x_), y(y_) {} constexpr Vec2(const T& x_, const T& y_) : x(x_), y(y_) {}
template <typename T2> template <typename T2>
constexpr Vec2<T2> Cast() const { [[nodiscard]] constexpr Vec2<T2> Cast() const {
return Vec2<T2>(static_cast<T2>(x), static_cast<T2>(y)); return Vec2<T2>(static_cast<T2>(x), static_cast<T2>(y));
} }
static constexpr Vec2 AssignToAll(const T& f) { [[nodiscard]] static constexpr Vec2 AssignToAll(const T& f) {
return Vec2{f, f}; return Vec2{f, f};
} }
constexpr Vec2<decltype(T{} + T{})> operator+(const Vec2& other) const { [[nodiscard]] constexpr Vec2<decltype(T{} + T{})> operator+(const Vec2& other) const {
return {x + other.x, y + other.y}; return {x + other.x, y + other.y};
} }
constexpr Vec2& operator+=(const Vec2& other) { constexpr Vec2& operator+=(const Vec2& other) {
@ -68,7 +68,7 @@ public:
y += other.y; y += other.y;
return *this; return *this;
} }
constexpr Vec2<decltype(T{} - T{})> operator-(const Vec2& other) const { [[nodiscard]] constexpr Vec2<decltype(T{} - T{})> operator-(const Vec2& other) const {
return {x - other.x, y - other.y}; return {x - other.x, y - other.y};
} }
constexpr Vec2& operator-=(const Vec2& other) { constexpr Vec2& operator-=(const Vec2& other) {
@ -78,15 +78,15 @@ public:
} }
template <typename U = T> template <typename U = T>
constexpr Vec2<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const { [[nodiscard]] constexpr Vec2<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const {
return {-x, -y}; return {-x, -y};
} }
constexpr Vec2<decltype(T{} * T{})> operator*(const Vec2& other) const { [[nodiscard]] constexpr Vec2<decltype(T{} * T{})> operator*(const Vec2& other) const {
return {x * other.x, y * other.y}; return {x * other.x, y * other.y};
} }
template <typename V> template <typename V>
constexpr Vec2<decltype(T{} * V{})> operator*(const V& f) const { [[nodiscard]] constexpr Vec2<decltype(T{} * V{})> operator*(const V& f) const {
return {x * f, y * f}; return {x * f, y * f};
} }
@ -97,7 +97,7 @@ public:
} }
template <typename V> template <typename V>
constexpr Vec2<decltype(T{} / V{})> operator/(const V& f) const { [[nodiscard]] constexpr Vec2<decltype(T{} / V{})> operator/(const V& f) const {
return {x / f, y / f}; return {x / f, y / f};
} }
@ -107,18 +107,18 @@ public:
return *this; return *this;
} }
constexpr T Length2() const { [[nodiscard]] constexpr T Length2() const {
return x * x + y * y; return x * x + y * y;
} }
// Only implemented for T=float // Only implemented for T=float
float Length() const; [[nodiscard]] float Length() const;
float Normalize(); // returns the previous length, which is often useful [[nodiscard]] float Normalize(); // returns the previous length, which is often useful
constexpr T& operator[](std::size_t i) { [[nodiscard]] constexpr T& operator[](std::size_t i) {
return *((&x) + i); return *((&x) + i);
} }
constexpr const T& operator[](std::size_t i) const { [[nodiscard]] constexpr const T& operator[](std::size_t i) const {
return *((&x) + i); return *((&x) + i);
} }
@ -128,46 +128,46 @@ public:
} }
// Common aliases: UV (texel coordinates), ST (texture coordinates) // Common aliases: UV (texel coordinates), ST (texture coordinates)
constexpr T& u() { [[nodiscard]] constexpr T& u() {
return x; return x;
} }
constexpr T& v() { [[nodiscard]] constexpr T& v() {
return y; return y;
} }
constexpr T& s() { [[nodiscard]] constexpr T& s() {
return x; return x;
} }
constexpr T& t() { [[nodiscard]] constexpr T& t() {
return y; return y;
} }
constexpr const T& u() const { [[nodiscard]] constexpr const T& u() const {
return x; return x;
} }
constexpr const T& v() const { [[nodiscard]] constexpr const T& v() const {
return y; return y;
} }
constexpr const T& s() const { [[nodiscard]] constexpr const T& s() const {
return x; return x;
} }
constexpr const T& t() const { [[nodiscard]] constexpr const T& t() const {
return y; return y;
} }
// swizzlers - create a subvector of specific components // swizzlers - create a subvector of specific components
constexpr Vec2 yx() const { [[nodiscard]] constexpr Vec2 yx() const {
return Vec2(y, x); return Vec2(y, x);
} }
constexpr Vec2 vu() const { [[nodiscard]] constexpr Vec2 vu() const {
return Vec2(y, x); return Vec2(y, x);
} }
constexpr Vec2 ts() const { [[nodiscard]] constexpr Vec2 ts() const {
return Vec2(y, x); return Vec2(y, x);
} }
}; };
template <typename T, typename V> template <typename T, typename V>
constexpr Vec2<T> operator*(const V& f, const Vec2<T>& vec) { [[nodiscard]] constexpr Vec2<T> operator*(const V& f, const Vec2<T>& vec) {
return Vec2<T>(f * vec.x, f * vec.y); return Vec2<T>(f * vec.x, f * vec.y);
} }
@ -196,15 +196,15 @@ public:
constexpr Vec3(const T& x_, const T& y_, const T& z_) : x(x_), y(y_), z(z_) {} constexpr Vec3(const T& x_, const T& y_, const T& z_) : x(x_), y(y_), z(z_) {}
template <typename T2> template <typename T2>
constexpr Vec3<T2> Cast() const { [[nodiscard]] constexpr Vec3<T2> Cast() const {
return Vec3<T2>(static_cast<T2>(x), static_cast<T2>(y), static_cast<T2>(z)); return Vec3<T2>(static_cast<T2>(x), static_cast<T2>(y), static_cast<T2>(z));
} }
static constexpr Vec3 AssignToAll(const T& f) { [[nodiscard]] static constexpr Vec3 AssignToAll(const T& f) {
return Vec3(f, f, f); return Vec3(f, f, f);
} }
constexpr Vec3<decltype(T{} + T{})> operator+(const Vec3& other) const { [[nodiscard]] constexpr Vec3<decltype(T{} + T{})> operator+(const Vec3& other) const {
return {x + other.x, y + other.y, z + other.z}; return {x + other.x, y + other.y, z + other.z};
} }
@ -215,7 +215,7 @@ public:
return *this; return *this;
} }
constexpr Vec3<decltype(T{} - T{})> operator-(const Vec3& other) const { [[nodiscard]] constexpr Vec3<decltype(T{} - T{})> operator-(const Vec3& other) const {
return {x - other.x, y - other.y, z - other.z}; return {x - other.x, y - other.y, z - other.z};
} }
@ -227,16 +227,16 @@ public:
} }
template <typename U = T> template <typename U = T>
constexpr Vec3<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const { [[nodiscard]] constexpr Vec3<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const {
return {-x, -y, -z}; return {-x, -y, -z};
} }
constexpr Vec3<decltype(T{} * T{})> operator*(const Vec3& other) const { [[nodiscard]] constexpr Vec3<decltype(T{} * T{})> operator*(const Vec3& other) const {
return {x * other.x, y * other.y, z * other.z}; return {x * other.x, y * other.y, z * other.z};
} }
template <typename V> template <typename V>
constexpr Vec3<decltype(T{} * V{})> operator*(const V& f) const { [[nodiscard]] constexpr Vec3<decltype(T{} * V{})> operator*(const V& f) const {
return {x * f, y * f, z * f}; return {x * f, y * f, z * f};
} }
@ -246,7 +246,7 @@ public:
return *this; return *this;
} }
template <typename V> template <typename V>
constexpr Vec3<decltype(T{} / V{})> operator/(const V& f) const { [[nodiscard]] constexpr Vec3<decltype(T{} / V{})> operator/(const V& f) const {
return {x / f, y / f, z / f}; return {x / f, y / f, z / f};
} }
@ -256,20 +256,20 @@ public:
return *this; return *this;
} }
constexpr T Length2() const { [[nodiscard]] constexpr T Length2() const {
return x * x + y * y + z * z; return x * x + y * y + z * z;
} }
// Only implemented for T=float // Only implemented for T=float
float Length() const; [[nodiscard]] float Length() const;
Vec3 Normalized() const; [[nodiscard]] Vec3 Normalized() const;
float Normalize(); // returns the previous length, which is often useful [[nodiscard]] float Normalize(); // returns the previous length, which is often useful
constexpr T& operator[](std::size_t i) { [[nodiscard]] constexpr T& operator[](std::size_t i) {
return *((&x) + i); return *((&x) + i);
} }
constexpr const T& operator[](std::size_t i) const { [[nodiscard]] constexpr const T& operator[](std::size_t i) const {
return *((&x) + i); return *((&x) + i);
} }
@ -280,63 +280,63 @@ public:
} }
// Common aliases: UVW (texel coordinates), RGB (colors), STQ (texture coordinates) // Common aliases: UVW (texel coordinates), RGB (colors), STQ (texture coordinates)
constexpr T& u() { [[nodiscard]] constexpr T& u() {
return x; return x;
} }
constexpr T& v() { [[nodiscard]] constexpr T& v() {
return y; return y;
} }
constexpr T& w() { [[nodiscard]] constexpr T& w() {
return z; return z;
} }
constexpr T& r() { [[nodiscard]] constexpr T& r() {
return x; return x;
} }
constexpr T& g() { [[nodiscard]] constexpr T& g() {
return y; return y;
} }
constexpr T& b() { [[nodiscard]] constexpr T& b() {
return z; return z;
} }
constexpr T& s() { [[nodiscard]] constexpr T& s() {
return x; return x;
} }
constexpr T& t() { [[nodiscard]] constexpr T& t() {
return y; return y;
} }
constexpr T& q() { [[nodiscard]] constexpr T& q() {
return z; return z;
} }
constexpr const T& u() const { [[nodiscard]] constexpr const T& u() const {
return x; return x;
} }
constexpr const T& v() const { [[nodiscard]] constexpr const T& v() const {
return y; return y;
} }
constexpr const T& w() const { [[nodiscard]] constexpr const T& w() const {
return z; return z;
} }
constexpr const T& r() const { [[nodiscard]] constexpr const T& r() const {
return x; return x;
} }
constexpr const T& g() const { [[nodiscard]] constexpr const T& g() const {
return y; return y;
} }
constexpr const T& b() const { [[nodiscard]] constexpr const T& b() const {
return z; return z;
} }
constexpr const T& s() const { [[nodiscard]] constexpr const T& s() const {
return x; return x;
} }
constexpr const T& t() const { [[nodiscard]] constexpr const T& t() const {
return y; return y;
} }
constexpr const T& q() const { [[nodiscard]] constexpr const T& q() const {
return z; return z;
} }
@ -345,7 +345,7 @@ public:
// _DEFINE_SWIZZLER2 defines a single such function, DEFINE_SWIZZLER2 defines all of them for all // _DEFINE_SWIZZLER2 defines a single such function, DEFINE_SWIZZLER2 defines all of them for all
// component names (x<->r) and permutations (xy<->yx) // component names (x<->r) and permutations (xy<->yx)
#define _DEFINE_SWIZZLER2(a, b, name) \ #define _DEFINE_SWIZZLER2(a, b, name) \
constexpr Vec2<T> name() const { \ [[nodiscard]] constexpr Vec2<T> name() const { \
return Vec2<T>(a, b); \ return Vec2<T>(a, b); \
} }
#define DEFINE_SWIZZLER2(a, b, a2, b2, a3, b3, a4, b4) \ #define DEFINE_SWIZZLER2(a, b, a2, b2, a3, b3, a4, b4) \
@ -366,7 +366,7 @@ public:
}; };
template <typename T, typename V> template <typename T, typename V>
constexpr Vec3<T> operator*(const V& f, const Vec3<T>& vec) { [[nodiscard]] constexpr Vec3<T> operator*(const V& f, const Vec3<T>& vec) {
return Vec3<T>(f * vec.x, f * vec.y, f * vec.z); return Vec3<T>(f * vec.x, f * vec.y, f * vec.z);
} }
@ -402,16 +402,16 @@ public:
: x(x_), y(y_), z(z_), w(w_) {} : x(x_), y(y_), z(z_), w(w_) {}
template <typename T2> template <typename T2>
constexpr Vec4<T2> Cast() const { [[nodiscard]] constexpr Vec4<T2> Cast() const {
return Vec4<T2>(static_cast<T2>(x), static_cast<T2>(y), static_cast<T2>(z), return Vec4<T2>(static_cast<T2>(x), static_cast<T2>(y), static_cast<T2>(z),
static_cast<T2>(w)); static_cast<T2>(w));
} }
static constexpr Vec4 AssignToAll(const T& f) { [[nodiscard]] static constexpr Vec4 AssignToAll(const T& f) {
return Vec4(f, f, f, f); return Vec4(f, f, f, f);
} }
constexpr Vec4<decltype(T{} + T{})> operator+(const Vec4& other) const { [[nodiscard]] constexpr Vec4<decltype(T{} + T{})> operator+(const Vec4& other) const {
return {x + other.x, y + other.y, z + other.z, w + other.w}; return {x + other.x, y + other.y, z + other.z, w + other.w};
} }
@ -423,7 +423,7 @@ public:
return *this; return *this;
} }
constexpr Vec4<decltype(T{} - T{})> operator-(const Vec4& other) const { [[nodiscard]] constexpr Vec4<decltype(T{} - T{})> operator-(const Vec4& other) const {
return {x - other.x, y - other.y, z - other.z, w - other.w}; return {x - other.x, y - other.y, z - other.z, w - other.w};
} }
@ -436,16 +436,16 @@ public:
} }
template <typename U = T> template <typename U = T>
constexpr Vec4<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const { [[nodiscard]] constexpr Vec4<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const {
return {-x, -y, -z, -w}; return {-x, -y, -z, -w};
} }
constexpr Vec4<decltype(T{} * T{})> operator*(const Vec4& other) const { [[nodiscard]] constexpr Vec4<decltype(T{} * T{})> operator*(const Vec4& other) const {
return {x * other.x, y * other.y, z * other.z, w * other.w}; return {x * other.x, y * other.y, z * other.z, w * other.w};
} }
template <typename V> template <typename V>
constexpr Vec4<decltype(T{} * V{})> operator*(const V& f) const { [[nodiscard]] constexpr Vec4<decltype(T{} * V{})> operator*(const V& f) const {
return {x * f, y * f, z * f, w * f}; return {x * f, y * f, z * f, w * f};
} }
@ -456,7 +456,7 @@ public:
} }
template <typename V> template <typename V>
constexpr Vec4<decltype(T{} / V{})> operator/(const V& f) const { [[nodiscard]] constexpr Vec4<decltype(T{} / V{})> operator/(const V& f) const {
return {x / f, y / f, z / f, w / f}; return {x / f, y / f, z / f, w / f};
} }
@ -466,15 +466,15 @@ public:
return *this; return *this;
} }
constexpr T Length2() const { [[nodiscard]] constexpr T Length2() const {
return x * x + y * y + z * z + w * w; return x * x + y * y + z * z + w * w;
} }
constexpr T& operator[](std::size_t i) { [[nodiscard]] constexpr T& operator[](std::size_t i) {
return *((&x) + i); return *((&x) + i);
} }
constexpr const T& operator[](std::size_t i) const { [[nodiscard]] constexpr const T& operator[](std::size_t i) const {
return *((&x) + i); return *((&x) + i);
} }
@ -486,29 +486,29 @@ public:
} }
// Common alias: RGBA (colors) // Common alias: RGBA (colors)
constexpr T& r() { [[nodiscard]] constexpr T& r() {
return x; return x;
} }
constexpr T& g() { [[nodiscard]] constexpr T& g() {
return y; return y;
} }
constexpr T& b() { [[nodiscard]] constexpr T& b() {
return z; return z;
} }
constexpr T& a() { [[nodiscard]] constexpr T& a() {
return w; return w;
} }
constexpr const T& r() const { [[nodiscard]] constexpr const T& r() const {
return x; return x;
} }
constexpr const T& g() const { [[nodiscard]] constexpr const T& g() const {
return y; return y;
} }
constexpr const T& b() const { [[nodiscard]] constexpr const T& b() const {
return z; return z;
} }
constexpr const T& a() const { [[nodiscard]] constexpr const T& a() const {
return w; return w;
} }
@ -520,7 +520,7 @@ public:
// DEFINE_SWIZZLER2_COMP2 defines two component functions for all component names (x<->r) and // DEFINE_SWIZZLER2_COMP2 defines two component functions for all component names (x<->r) and
// permutations (xy<->yx) // permutations (xy<->yx)
#define _DEFINE_SWIZZLER2(a, b, name) \ #define _DEFINE_SWIZZLER2(a, b, name) \
constexpr Vec2<T> name() const { \ [[nodiscard]] constexpr Vec2<T> name() const { \
return Vec2<T>(a, b); \ return Vec2<T>(a, b); \
} }
#define DEFINE_SWIZZLER2_COMP1(a, a2) \ #define DEFINE_SWIZZLER2_COMP1(a, a2) \
@ -547,7 +547,7 @@ public:
#undef _DEFINE_SWIZZLER2 #undef _DEFINE_SWIZZLER2
#define _DEFINE_SWIZZLER3(a, b, c, name) \ #define _DEFINE_SWIZZLER3(a, b, c, name) \
constexpr Vec3<T> name() const { \ [[nodiscard]] constexpr Vec3<T> name() const { \
return Vec3<T>(a, b, c); \ return Vec3<T>(a, b, c); \
} }
#define DEFINE_SWIZZLER3_COMP1(a, a2) \ #define DEFINE_SWIZZLER3_COMP1(a, a2) \
@ -581,7 +581,7 @@ public:
}; };
template <typename T, typename V> template <typename T, typename V>
constexpr Vec4<decltype(V{} * T{})> operator*(const V& f, const Vec4<T>& vec) { [[nodiscard]] constexpr Vec4<decltype(V{} * T{})> operator*(const V& f, const Vec4<T>& vec) {
return {f * vec.x, f * vec.y, f * vec.z, f * vec.w}; return {f * vec.x, f * vec.y, f * vec.z, f * vec.w};
} }
@ -593,30 +593,32 @@ constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec2<T>& a, const Vec2<T>& b
} }
template <typename T> template <typename T>
constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec3<T>& a, const Vec3<T>& b) { [[nodiscard]] constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec3<T>& a, const Vec3<T>& b) {
return a.x * b.x + a.y * b.y + a.z * b.z; return a.x * b.x + a.y * b.y + a.z * b.z;
} }
template <typename T> template <typename T>
constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec4<T>& a, const Vec4<T>& b) { [[nodiscard]] constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec4<T>& a, const Vec4<T>& b) {
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
} }
template <typename T> template <typename T>
constexpr Vec3<decltype(T{} * T{} - T{} * T{})> Cross(const Vec3<T>& a, const Vec3<T>& b) { [[nodiscard]] constexpr Vec3<decltype(T{} * T{} - T{} * T{})> Cross(const Vec3<T>& a,
const Vec3<T>& b) {
return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x}; return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x};
} }
// linear interpolation via float: 0.0=begin, 1.0=end // linear interpolation via float: 0.0=begin, 1.0=end
template <typename X> template <typename X>
constexpr decltype(X{} * float{} + X{} * float{}) Lerp(const X& begin, const X& end, [[nodiscard]] constexpr decltype(X{} * float{} + X{} * float{}) Lerp(const X& begin, const X& end,
const float t) { const float t) {
return begin * (1.f - t) + end * t; return begin * (1.f - t) + end * t;
} }
// linear interpolation via int: 0=begin, base=end // linear interpolation via int: 0=begin, base=end
template <typename X, int base> template <typename X, int base>
constexpr decltype((X{} * int{} + X{} * int{}) / base) LerpInt(const X& begin, const X& end, [[nodiscard]] constexpr decltype((X{} * int{} + X{} * int{}) / base) LerpInt(const X& begin,
const X& end,
const int t) { const int t) {
return (begin * (base - t) + end * t) / base; return (begin * (base - t) + end * t) / base;
} }
@ -624,8 +626,8 @@ constexpr decltype((X{} * int{} + X{} * int{}) / base) LerpInt(const X& begin, c
// bilinear interpolation. s is for interpolating x00-x01 and x10-x11, and t is for the second // bilinear interpolation. s is for interpolating x00-x01 and x10-x11, and t is for the second
// interpolation. // interpolation.
template <typename X> template <typename X>
constexpr auto BilinearInterp(const X& x00, const X& x01, const X& x10, const X& x11, const float s, [[nodiscard]] constexpr auto BilinearInterp(const X& x00, const X& x01, const X& x10, const X& x11,
const float t) { const float s, const float t) {
auto y0 = Lerp(x00, x01, s); auto y0 = Lerp(x00, x01, s);
auto y1 = Lerp(x10, x11, s); auto y1 = Lerp(x10, x11, s);
return Lerp(y0, y1, t); return Lerp(y0, y1, t);
@ -633,42 +635,42 @@ constexpr auto BilinearInterp(const X& x00, const X& x01, const X& x10, const X&
// Utility vector factories // Utility vector factories
template <typename T> template <typename T>
constexpr Vec2<T> MakeVec(const T& x, const T& y) { [[nodiscard]] constexpr Vec2<T> MakeVec(const T& x, const T& y) {
return Vec2<T>{x, y}; return Vec2<T>{x, y};
} }
template <typename T> template <typename T>
constexpr Vec3<T> MakeVec(const T& x, const T& y, const T& z) { [[nodiscard]] constexpr Vec3<T> MakeVec(const T& x, const T& y, const T& z) {
return Vec3<T>{x, y, z}; return Vec3<T>{x, y, z};
} }
template <typename T> template <typename T>
constexpr Vec4<T> MakeVec(const T& x, const T& y, const Vec2<T>& zw) { [[nodiscard]] constexpr Vec4<T> MakeVec(const T& x, const T& y, const Vec2<T>& zw) {
return MakeVec(x, y, zw[0], zw[1]); return MakeVec(x, y, zw[0], zw[1]);
} }
template <typename T> template <typename T>
constexpr Vec3<T> MakeVec(const Vec2<T>& xy, const T& z) { [[nodiscard]] constexpr Vec3<T> MakeVec(const Vec2<T>& xy, const T& z) {
return MakeVec(xy[0], xy[1], z); return MakeVec(xy[0], xy[1], z);
} }
template <typename T> template <typename T>
constexpr Vec3<T> MakeVec(const T& x, const Vec2<T>& yz) { [[nodiscard]] constexpr Vec3<T> MakeVec(const T& x, const Vec2<T>& yz) {
return MakeVec(x, yz[0], yz[1]); return MakeVec(x, yz[0], yz[1]);
} }
template <typename T> template <typename T>
constexpr Vec4<T> MakeVec(const T& x, const T& y, const T& z, const T& w) { [[nodiscard]] constexpr Vec4<T> MakeVec(const T& x, const T& y, const T& z, const T& w) {
return Vec4<T>{x, y, z, w}; return Vec4<T>{x, y, z, w};
} }
template <typename T> template <typename T>
constexpr Vec4<T> MakeVec(const Vec2<T>& xy, const T& z, const T& w) { [[nodiscard]] constexpr Vec4<T> MakeVec(const Vec2<T>& xy, const T& z, const T& w) {
return MakeVec(xy[0], xy[1], z, w); return MakeVec(xy[0], xy[1], z, w);
} }
template <typename T> template <typename T>
constexpr Vec4<T> MakeVec(const T& x, const Vec2<T>& yz, const T& w) { [[nodiscard]] constexpr Vec4<T> MakeVec(const T& x, const Vec2<T>& yz, const T& w) {
return MakeVec(x, yz[0], yz[1], w); return MakeVec(x, yz[0], yz[1], w);
} }
@ -676,17 +678,17 @@ constexpr Vec4<T> MakeVec(const T& x, const Vec2<T>& yz, const T& w) {
// Even if someone wanted to use an odd object like Vec2<Vec2<T>>, the compiler would error // Even if someone wanted to use an odd object like Vec2<Vec2<T>>, the compiler would error
// out soon enough due to misuse of the returned structure. // out soon enough due to misuse of the returned structure.
template <typename T> template <typename T>
constexpr Vec4<T> MakeVec(const Vec2<T>& xy, const Vec2<T>& zw) { [[nodiscard]] constexpr Vec4<T> MakeVec(const Vec2<T>& xy, const Vec2<T>& zw) {
return MakeVec(xy[0], xy[1], zw[0], zw[1]); return MakeVec(xy[0], xy[1], zw[0], zw[1]);
} }
template <typename T> template <typename T>
constexpr Vec4<T> MakeVec(const Vec3<T>& xyz, const T& w) { [[nodiscard]] constexpr Vec4<T> MakeVec(const Vec3<T>& xyz, const T& w) {
return MakeVec(xyz[0], xyz[1], xyz[2], w); return MakeVec(xyz[0], xyz[1], xyz[2], w);
} }
template <typename T> template <typename T>
constexpr Vec4<T> MakeVec(const T& x, const Vec3<T>& yzw) { [[nodiscard]] constexpr Vec4<T> MakeVec(const T& x, const Vec3<T>& yzw) {
return MakeVec(x, yzw[0], yzw[1], yzw[2]); return MakeVec(x, yzw[0], yzw[1], yzw[2]);
} }

View file

@ -30,23 +30,23 @@ public:
base_ptr = reinterpret_cast<T*>(AllocateMemoryPages(alloc_size)); base_ptr = reinterpret_cast<T*>(AllocateMemoryPages(alloc_size));
} }
constexpr const T& operator[](std::size_t index) const { [[nodiscard]] constexpr const T& operator[](std::size_t index) const {
return base_ptr[index]; return base_ptr[index];
} }
constexpr T& operator[](std::size_t index) { [[nodiscard]] constexpr T& operator[](std::size_t index) {
return base_ptr[index]; return base_ptr[index];
} }
constexpr T* data() { [[nodiscard]] constexpr T* data() {
return base_ptr; return base_ptr;
} }
constexpr const T* data() const { [[nodiscard]] constexpr const T* data() const {
return base_ptr; return base_ptr;
} }
constexpr std::size_t size() const { [[nodiscard]] constexpr std::size_t size() const {
return alloc_size / sizeof(T); return alloc_size / sizeof(T);
} }

View file

@ -14,24 +14,24 @@ namespace Common {
class WallClock { class WallClock {
public: public:
/// Returns current wall time in nanoseconds /// Returns current wall time in nanoseconds
virtual std::chrono::nanoseconds GetTimeNS() = 0; [[nodiscard]] virtual std::chrono::nanoseconds GetTimeNS() = 0;
/// Returns current wall time in microseconds /// Returns current wall time in microseconds
virtual std::chrono::microseconds GetTimeUS() = 0; [[nodiscard]] virtual std::chrono::microseconds GetTimeUS() = 0;
/// Returns current wall time in milliseconds /// Returns current wall time in milliseconds
virtual std::chrono::milliseconds GetTimeMS() = 0; [[nodiscard]] virtual std::chrono::milliseconds GetTimeMS() = 0;
/// Returns current wall time in emulated clock cycles /// Returns current wall time in emulated clock cycles
virtual u64 GetClockCycles() = 0; [[nodiscard]] virtual u64 GetClockCycles() = 0;
/// Returns current wall time in emulated cpu cycles /// Returns current wall time in emulated cpu cycles
virtual u64 GetCPUCycles() = 0; [[nodiscard]] virtual u64 GetCPUCycles() = 0;
virtual void Pause(bool is_paused) = 0; virtual void Pause(bool is_paused) = 0;
/// Tells if the wall clock, uses the host CPU's hardware clock /// Tells if the wall clock, uses the host CPU's hardware clock
bool IsNative() const { [[nodiscard]] bool IsNative() const {
return is_native; return is_native;
} }
@ -47,7 +47,7 @@ private:
bool is_native; bool is_native;
}; };
std::unique_ptr<WallClock> CreateBestMatchingClock(u32 emulated_cpu_frequency, [[nodiscard]] std::unique_ptr<WallClock> CreateBestMatchingClock(u32 emulated_cpu_frequency,
u32 emulated_clock_frequency); u32 emulated_clock_frequency);
} // namespace Common } // namespace Common

View file

@ -19,7 +19,7 @@ namespace Common::Compression {
* *
* @return the compressed data. * @return the compressed data.
*/ */
std::vector<u8> CompressDataZSTD(std::span<const u8> source, s32 compression_level); [[nodiscard]] std::vector<u8> CompressDataZSTD(std::span<const u8> source, s32 compression_level);
/** /**
* Compresses a source memory region with Zstandard with the default compression level and returns * Compresses a source memory region with Zstandard with the default compression level and returns
@ -29,7 +29,7 @@ std::vector<u8> CompressDataZSTD(std::span<const u8> source, s32 compression_lev
* *
* @return the compressed data. * @return the compressed data.
*/ */
std::vector<u8> CompressDataZSTDDefault(std::span<const u8> source); [[nodiscard]] std::vector<u8> CompressDataZSTDDefault(std::span<const u8> source);
/** /**
* Decompresses a source memory region with Zstandard and returns the uncompressed data in a vector. * Decompresses a source memory region with Zstandard and returns the uncompressed data in a vector.
@ -38,6 +38,6 @@ std::vector<u8> CompressDataZSTDDefault(std::span<const u8> source);
* *
* @return the decompressed data. * @return the decompressed data.
*/ */
std::vector<u8> DecompressDataZSTD(const std::vector<u8>& compressed); [[nodiscard]] std::vector<u8> DecompressDataZSTD(const std::vector<u8>& compressed);
} // namespace Common::Compression } // namespace Common::Compression