mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-13 23:46:40 +00:00
offsetof: proper detection when sizeof() != alignof
This commit is contained in:
parent
769a57526c
commit
9068e2071c
1 changed files with 9 additions and 8 deletions
|
@ -22,14 +22,15 @@ namespace ams::util {
|
||||||
|
|
||||||
namespace impl {
|
namespace impl {
|
||||||
|
|
||||||
template<size_t Alignment>
|
template<size_t MaxDepth>
|
||||||
struct OffsetOfUnionHolder {
|
struct OffsetOfUnionHolder {
|
||||||
template<typename ParentType, typename MemberType, size_t Offset>
|
template<typename ParentType, typename MemberType, size_t Offset>
|
||||||
union UnionImpl {
|
union UnionImpl {
|
||||||
|
using PaddingMember = std::array<char, alignof(ParentType)>;
|
||||||
static constexpr size_t GetOffset() { return Offset; }
|
static constexpr size_t GetOffset() { return Offset; }
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
char padding[Offset];
|
PaddingMember padding[Offset];
|
||||||
MemberType members[(sizeof(ParentType) / sizeof(MemberType)) + 1];
|
MemberType members[(sizeof(ParentType) / sizeof(MemberType)) + 1];
|
||||||
} data;
|
} data;
|
||||||
UnionImpl<ParentType, MemberType, Offset + 1> next_union;
|
UnionImpl<ParentType, MemberType, Offset + 1> next_union;
|
||||||
|
@ -46,12 +47,12 @@ namespace ams::util {
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ParentType, typename MemberType>
|
template<typename ParentType, typename MemberType>
|
||||||
union UnionImpl<ParentType, MemberType, Alignment> { /* Empty */ };
|
union UnionImpl<ParentType, MemberType, MaxDepth> { /* Empty */ };
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ParentType, typename MemberType>
|
template<typename ParentType, typename MemberType>
|
||||||
struct OffsetOfCalculator {
|
struct OffsetOfCalculator {
|
||||||
using UnionHolder = typename OffsetOfUnionHolder<alignof(MemberType)>::template UnionImpl<ParentType, MemberType, 0>;
|
using UnionHolder = typename OffsetOfUnionHolder<sizeof(MemberType) / alignof(MemberType) + 1>::template UnionImpl<ParentType, MemberType, 0>;
|
||||||
union Union {
|
union Union {
|
||||||
char c;
|
char c;
|
||||||
UnionHolder first_union;
|
UnionHolder first_union;
|
||||||
|
@ -80,15 +81,15 @@ namespace ams::util {
|
||||||
const auto start = std::addressof(cur_union.data.members[0]);
|
const auto start = std::addressof(cur_union.data.members[0]);
|
||||||
const auto next = GetNextAddress(start, target);
|
const auto next = GetNextAddress(start, target);
|
||||||
|
|
||||||
if (next < target) {
|
if (next != target) {
|
||||||
if constexpr (Offset + 1 < alignof(MemberType)) {
|
if constexpr (Offset < sizeof(MemberType) / alignof(MemberType)) {
|
||||||
return OffsetOfImpl(member, cur_union.next_union);
|
return OffsetOfImpl(member, cur_union.next_union);
|
||||||
} else {
|
} else {
|
||||||
static_assert(Offset + 1 <= alignof(MemberType));
|
std::abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (next - start) * sizeof(MemberType) + Offset;
|
return (next - start) * sizeof(MemberType) + Offset * alignof(MemberType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue