1
0
Fork 0
mirror of https://github.com/jugeeya/UltimateTrainingModpack.git synced 2025-01-20 17:30:13 +00:00
UltimateTrainingModpack/TrainingModpackOverlay/include/cpp_utils.hpp
2020-08-10 11:54:12 -07:00

159 lines
5.8 KiB
C++

#pragma once
#include <type_traits>
#include <cstdint>
#include <array>
namespace detail
{
template<class T, typename U = uint32_t> struct BitFlags
{
using UnderlyingType = U;
using Type = T;
constexpr static const UnderlyingType s_validMask = (UnderlyingType{1u << *Type::Count} - UnderlyingType{1});
struct NoneType
{};
struct AllType
{};
UnderlyingType m_bits;
constexpr static const AllType All{};
constexpr static const NoneType None{};
BitFlags() = default;
BitFlags(const BitFlags&) = default;
constexpr BitFlags(NoneType) : m_bits(0) {}
constexpr BitFlags(AllType) : m_bits(s_validMask) {}
constexpr explicit BitFlags(UnderlyingType t) : m_bits(s_validMask & t) {}
BitFlags& operator=(const BitFlags&) = default;
~BitFlags() = default;
constexpr BitFlags(Type t) : m_bits{UnderlyingType{1} << static_cast<std::underlying_type_t<Type>>(t)} {}
constexpr BitFlags& operator|=(BitFlags rhs)
{
m_bits |= rhs.m_bits;
return *this;
}
constexpr BitFlags& operator&=(BitFlags rhs)
{
m_bits &= rhs.m_bits;
return *this;
}
constexpr BitFlags& operator-=(BitFlags rhs)
{
m_bits &= ~rhs.m_bits;
return *this;
}
explicit operator bool() const { return m_bits != 0; }
};
template<typename T, typename U> constexpr BitFlags<T, U> operator|(BitFlags<T, U> lhs, BitFlags<T, U> rhs)
{
lhs |= rhs;
return lhs;
}
template<typename T, typename U> constexpr BitFlags<T, U> operator&(BitFlags<T, U> lhs, BitFlags<T, U> rhs)
{
lhs &= rhs;
return lhs;
}
template<typename T, typename U> constexpr BitFlags<T, U> operator-(BitFlags<T, U> lhs, BitFlags<T, U> rhs)
{
lhs -= rhs;
return lhs;
}
template<typename T, typename U> constexpr BitFlags<T, U> operator-(BitFlags<T, U> lhs, T rhs)
{
lhs -= rhs;
return lhs;
}
template<typename T, typename U> constexpr BitFlags<T, U> operator-(T lhs, BitFlags<T, U> rhs)
{
rhs -= lhs;
return rhs;
}
template<typename T, typename U> constexpr BitFlags<T, U> operator|(BitFlags<T, U> lhs, T rhs)
{
lhs |= rhs;
return lhs;
}
template<typename T, typename U> constexpr BitFlags<T, U> operator|(T lhs, BitFlags<T, U> rhs)
{
rhs |= lhs;
return rhs;
}
template<typename T, typename U> constexpr bool operator&(BitFlags<T, U> lhs, T rhs)
{
lhs &= rhs;
return lhs.m_bits != 0;
}
template<typename T, typename U> constexpr bool operator&(T lhs, BitFlags<T, U> rhs)
{
rhs &= lhs;
return rhs.m_bits != 0;
}
template<typename T> struct FlagType;
template<typename T> using FlagTypeT = typename FlagType<T>::Type;
template<class T> struct EnumArray;
} // namespace detail
#define DEFINE_FLAGS_UT(TypeName, UnderlyingType) \
using TypeName##s = detail::BitFlags<TypeName, UnderlyingType>; \
constexpr TypeName##s operator|(TypeName lhs, TypeName rhs) { return TypeName##s{lhs} | TypeName##s{rhs}; } \
namespace detail \
{ \
template<> struct FlagType<TypeName> \
{ \
using Type = TypeName##s; \
}; \
}
#define DEFINE_FLAGS(TypeName) DEFINE_FLAGS_UT(TypeName, uint32_t)
#define ENUM_X(type, e, y) e,
#define ENUM_QUAL_X(type, e, y) type::e,
#define ENUM_NAME_PAIR(type, e, y) {type::e, y},
#define CASE_X(type, e, y) \
case type::e: \
return y;
#define DEFINE_ENUM_CLASS_TYPE(Name, Type) \
enum class Name : Type \
{ \
ENUM_CLASS_##Name(Name, ENUM_X) Count \
}; \
constexpr auto operator*(Name t) { return static_cast<std::underlying_type_t<Name>>(t); } \
namespace detail \
{ \
template<> struct EnumArray<Name> \
{ \
constexpr static const std::array<std::pair<Name, const char*>, *Name::Count> values{ \
{ENUM_CLASS_##Name(Name, ENUM_NAME_PAIR)}}; \
}; \
} \
constexpr const char* toString(Name t) \
{ \
if(t < Name::Count) \
{ \
return detail::EnumArray<Name>::values[*t].second; \
} \
return "UNKNWON"; \
} \
DEFINE_FLAGS_UT(Name, Type)
#define DEFINE_ENUM_CLASS(Name) DEFINE_ENUM_CLASS_TYPE(Name, uint32_t)