mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-12-28 05:06:08 +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 {
|
||||
|
||||
template<size_t Alignment>
|
||||
template<size_t MaxDepth>
|
||||
struct OffsetOfUnionHolder {
|
||||
template<typename ParentType, typename MemberType, size_t Offset>
|
||||
union UnionImpl {
|
||||
using PaddingMember = std::array<char, alignof(ParentType)>;
|
||||
static constexpr size_t GetOffset() { return Offset; }
|
||||
|
||||
struct {
|
||||
char padding[Offset];
|
||||
PaddingMember padding[Offset];
|
||||
MemberType members[(sizeof(ParentType) / sizeof(MemberType)) + 1];
|
||||
} data;
|
||||
UnionImpl<ParentType, MemberType, Offset + 1> next_union;
|
||||
|
@ -46,12 +47,12 @@ namespace ams::util {
|
|||
};
|
||||
|
||||
template<typename ParentType, typename MemberType>
|
||||
union UnionImpl<ParentType, MemberType, Alignment> { /* Empty */ };
|
||||
union UnionImpl<ParentType, MemberType, MaxDepth> { /* Empty */ };
|
||||
};
|
||||
|
||||
template<typename ParentType, typename MemberType>
|
||||
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 {
|
||||
char c;
|
||||
UnionHolder first_union;
|
||||
|
@ -80,15 +81,15 @@ namespace ams::util {
|
|||
const auto start = std::addressof(cur_union.data.members[0]);
|
||||
const auto next = GetNextAddress(start, target);
|
||||
|
||||
if (next < target) {
|
||||
if constexpr (Offset + 1 < alignof(MemberType)) {
|
||||
if (next != target) {
|
||||
if constexpr (Offset < sizeof(MemberType) / alignof(MemberType)) {
|
||||
return OffsetOfImpl(member, cur_union.next_union);
|
||||
} 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