1
0
Fork 0
mirror of https://github.com/Atmosphere-NX/Atmosphere.git synced 2025-02-04 07:45:06 +00:00
Atmosphere/mesosphere/include/mesosphere/core/util.hpp
2019-06-03 17:41:00 -07:00

109 lines
3.3 KiB
C++

#pragma once
#include <utility>
#include <array>
#include <boost/assert.hpp>
#include <mesosphere/core/types.hpp>
/*
Boost doesn't provide get_parent_from members for arrays so we have to implement this manually
for arrays, for gcc at leadt.
Thanks fincs.
*/
#define kassert(cond) ((void)(cond))
namespace mesosphere
{
namespace
{
template <typename ClassT, typename MemberT>
union __my_offsetof {
const MemberT ClassT::* ptr;
iptr offset;
};
// Thanks neobrain
template<typename T, size_t N, typename... Args, size_t... Indexes>
static constexpr std::array<T, N> MakeArrayOfHelper(Args&&... args, std::index_sequence<Indexes...>) {
// There are two parameter pack expansions here:
// * The inner expansion is over "t"
// * The outer expansion is over "Indexes"
//
// This function will always be called with sizeof...(Indexes) == N,
// so the outer expansion generates exactly N copies of the constructor call
return std::array<T, N> { ((void)Indexes, T { args... })... };
}
// Thanks neobrain
template<typename T, typename F, size_t N, typename... Args, size_t... Indexes>
static constexpr std::array<T, N> MakeArrayWithFactorySequenceOfHelper(Args&&... args, std::index_sequence<Indexes...>) {
return std::array<T, N> { T { F{}(std::integral_constant<size_t, Indexes>{}), args... }... };
}
}
namespace detail
{
template <typename ClassT, typename MemberT, size_t N>
constexpr ClassT* GetParentFromArrayMember(MemberT* member, size_t index, const MemberT (ClassT::* ptr)[N]) noexcept {
member -= index;
return (ClassT*)((iptr)member - __my_offsetof<ClassT,MemberT[N]> { ptr }.offset);
return nullptr;
}
template <typename ClassT, typename MemberT, size_t N>
constexpr const ClassT* GetParentFromArrayMember(const MemberT* member, size_t index, const MemberT (ClassT::* ptr)[N]) noexcept {
member -= index;
return (const ClassT*)((iptr)member - __my_offsetof<ClassT,MemberT[N]> { ptr }.offset);
return nullptr;
}
template <typename ClassT, typename MemberT>
constexpr ClassT* GetParentFromMember(MemberT* member, const MemberT ClassT::* ptr) noexcept {
return (ClassT*)((iptr)member - __my_offsetof<ClassT, MemberT> { ptr }.offset);
return nullptr;
}
template <typename ClassT, typename MemberT>
constexpr const ClassT* GetParentFromMember(const MemberT* member, const MemberT ClassT::* ptr) noexcept {
return (const ClassT*)((iptr)member - __my_offsetof<ClassT, MemberT> { ptr }.offset);
return nullptr;
}
template<typename T, size_t N, typename... Args>
constexpr std::array<T, N> MakeArrayOf(Args&&... args) {
return MakeArrayOfHelper<T, N, Args...>(std::forward<Args>(args)..., std::make_index_sequence<N>{});
}
template<typename T, typename F, size_t N, typename... Args>
constexpr std::array<T, N> MakeArrayWithFactorySequenceOf(Args&&... args) {
return MakeArrayWithFactorySequenceOfHelper<T, F, N, Args...>(std::forward<Args>(args)..., std::make_index_sequence<N>{});
}
/// Sequence of two distinc powers of 2
constexpr ulong A038444(ulong n)
{
if (n == 0) {
return 3;
}
ulong v = A038444(n - 1);
ulong m1 = 1 << (63 - __builtin_clzl(v));
ulong m2 = 1 << (63 - __builtin_clzl(v&~m1));
if (m2 << 1 == m1) {
m2 = 1;
m1 <<= 1;
} else {
m2 <<= 1;
}
return m1 | m2;
}
}
}