mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-10-23 08:29:47 +00:00
Common/BitUtils: Add operator[] to BitCastPtrType
This commit is contained in:
parent
32e621765e
commit
e9f58193a7
2 changed files with 66 additions and 1 deletions
|
@ -154,14 +154,27 @@ public:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline auto operator[](std::size_t index) const
|
||||||
|
{
|
||||||
|
using S = std::conditional_t<std::is_const<PtrType>::value, const std::byte, std::byte>;
|
||||||
|
S* const target = reinterpret_cast<S*>(m_ptr) + index * sizeof(T);
|
||||||
|
return BitCastPtrType<T, S>{target};
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PtrType* m_ptr;
|
PtrType* m_ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Provides an aliasing-safe alternative to reinterpret_cast'ing pointers to structs
|
// Provides an aliasing-safe alternative to reinterpret_cast'ing pointers to structs
|
||||||
// Conversion constructor and operator= provided for a convenient syntax.
|
// Conversion constructor and operator= provided for a convenient syntax.
|
||||||
// Usage: MyStruct s = BitCastPtr<MyStruct>(some_ptr);
|
// Usage:
|
||||||
|
// MyStruct s = BitCastPtr<MyStruct>(some_ptr);
|
||||||
// BitCastPtr<MyStruct>(some_ptr) = s;
|
// BitCastPtr<MyStruct>(some_ptr) = s;
|
||||||
|
//
|
||||||
|
// Array example:
|
||||||
|
// BitCastPtr<MyStruct> unaligned_array(unaligned_ptr);
|
||||||
|
// MyStruct s = unaligned_array[2];
|
||||||
|
// unaligned_array[2] = s;
|
||||||
template <typename T, typename PtrType>
|
template <typename T, typename PtrType>
|
||||||
inline auto BitCastPtr(PtrType* ptr) noexcept -> BitCastPtrType<T, PtrType>
|
inline auto BitCastPtr(PtrType* ptr) noexcept -> BitCastPtrType<T, PtrType>
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include <bit>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "Common/BitUtils.h"
|
#include "Common/BitUtils.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
|
|
||||||
|
@ -88,3 +91,52 @@ TEST(BitUtils, IsValidLowMask)
|
||||||
EXPECT_FALSE(Common::IsValidLowMask((u64) ~(0b10000)));
|
EXPECT_FALSE(Common::IsValidLowMask((u64) ~(0b10000)));
|
||||||
EXPECT_FALSE(Common::IsValidLowMask((u64)(~((u64)(~0b0) >> 1) | 0b1111)));
|
EXPECT_FALSE(Common::IsValidLowMask((u64)(~((u64)(~0b0) >> 1) | 0b1111)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(BitUtils, BitCastPtr)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(std::endian::native, std::endian::little);
|
||||||
|
|
||||||
|
std::vector<u8> data{0, 1, 0, 2, 0, 3, 0, 0xFF, 0xFF};
|
||||||
|
u8* buffer = data.data();
|
||||||
|
|
||||||
|
EXPECT_EQ(s16(1), Common::BitCastPtr<s16>(buffer + 1));
|
||||||
|
Common::BitCastPtr<s16>(buffer + 1) = s16(-1);
|
||||||
|
EXPECT_EQ(u16(0xFFFF), Common::BitCastPtr<u16>(buffer + 1));
|
||||||
|
EXPECT_EQ(data, std::vector<u8>({0, 0xFF, 0xFF, 2, 0, 3, 0, 0xFF, 0xFF}));
|
||||||
|
|
||||||
|
EXPECT_EQ(s32(0xFFFF0003), Common::BitCastPtr<s32>(buffer + 1)[1]);
|
||||||
|
Common::BitCastPtr<u32>(buffer + 1)[1] = u32(0xFFFFFFFF);
|
||||||
|
EXPECT_EQ(s32(-1), Common::BitCastPtr<s32>(buffer + 1)[1]);
|
||||||
|
EXPECT_EQ(data, std::vector<u8>({0, 0xFF, 0xFF, 2, 0, 0xFF, 0xFF, 0xFF, 0xFF}));
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct MyStruct
|
||||||
|
{
|
||||||
|
u16 v16;
|
||||||
|
u8 v8;
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
MyStruct s1 = Common::BitCastPtr<MyStruct>(buffer + 1);
|
||||||
|
EXPECT_EQ(u16(0xFFFF), s1.v16);
|
||||||
|
EXPECT_EQ(u8(2), s1.v8);
|
||||||
|
s1.v16 = 4;
|
||||||
|
s1.v8 = 5;
|
||||||
|
Common::BitCastPtr<MyStruct>(buffer + 1) = s1;
|
||||||
|
EXPECT_EQ(s16(4), Common::BitCastPtr<s16>(buffer + 1));
|
||||||
|
EXPECT_EQ(s8(5), Common::BitCastPtr<s8>(buffer + 3));
|
||||||
|
EXPECT_EQ(data, std::vector<u8>({0, 4, 0, 5, 0, 0xFF, 0xFF, 0xFF, 0xFF}));
|
||||||
|
|
||||||
|
auto struct_array = Common::BitCastPtr<MyStruct>(buffer + 1);
|
||||||
|
const MyStruct s1_again = struct_array[0];
|
||||||
|
EXPECT_EQ(u16(4), s1_again.v16);
|
||||||
|
EXPECT_EQ(u8(5), s1_again.v8);
|
||||||
|
MyStruct s2 = struct_array[1];
|
||||||
|
EXPECT_EQ(u16(0xFF00), s2.v16);
|
||||||
|
EXPECT_EQ(u8(0xFF), s2.v8);
|
||||||
|
struct_array[1] = s1_again;
|
||||||
|
s2 = struct_array[1];
|
||||||
|
EXPECT_EQ(u16(4), s2.v16);
|
||||||
|
EXPECT_EQ(u8(5), s2.v8);
|
||||||
|
EXPECT_EQ(data, std::vector<u8>({0, 4, 0, 5, 4, 0, 5, 0xFF, 0xFF}));
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue