mirror of
https://github.com/AxioDL/LibCommon.git
synced 2026-03-30 11:47:23 -07:00
146 lines
8.0 KiB
C++
146 lines
8.0 KiB
C++
#ifndef AXIO_FLAGS_H
|
|
#define AXIO_FLAGS_H
|
|
|
|
#include "Serialization/IArchive.h"
|
|
|
|
#include <compare>
|
|
#include <cstdint>
|
|
#include <type_traits>
|
|
|
|
template<typename FlagEnum>
|
|
requires(std::is_enum_v<FlagEnum>)
|
|
class TFlags
|
|
{
|
|
using UnsignedT = std::make_unsigned_t<std::underlying_type_t<FlagEnum>>;
|
|
|
|
UnsignedT mValue = 0;
|
|
|
|
public:
|
|
constexpr TFlags() = default;
|
|
constexpr TFlags(FlagEnum Val) : mValue(UnsignedT(Val)) {}
|
|
constexpr explicit TFlags(UnsignedT Val) : mValue(Val) {}
|
|
|
|
[[nodiscard]] constexpr explicit operator bool() const { return mValue != 0; }
|
|
[[nodiscard]] constexpr auto operator<=>(const TFlags&) const noexcept = default;
|
|
|
|
[[nodiscard]] constexpr TFlags operator~() const { return TFlags(UnsignedT(~mValue)); }
|
|
|
|
#define FLAG_BITWISE_OP_ENUM(op) \
|
|
constexpr TFlags operator op (FlagEnum val) const { \
|
|
return TFlags(FlagEnum(mValue op UnsignedT(val))); \
|
|
} \
|
|
constexpr TFlags operator op (const TFlags& val) const { \
|
|
return TFlags(mValue op val.mValue); \
|
|
}
|
|
FLAG_BITWISE_OP_ENUM(|)
|
|
FLAG_BITWISE_OP_ENUM(&)
|
|
FLAG_BITWISE_OP_ENUM(^)
|
|
#undef FLAG_BITWISE_OP_ENUM
|
|
|
|
#define FLAG_BITWISE_OP_ASSIGN_ENUM(op) \
|
|
constexpr TFlags& operator op (FlagEnum val) { \
|
|
mValue op UnsignedT(val); \
|
|
return *this; \
|
|
} \
|
|
constexpr TFlags& operator op (const TFlags& val) { \
|
|
mValue op val.mValue; \
|
|
return *this; \
|
|
}
|
|
FLAG_BITWISE_OP_ASSIGN_ENUM(|=)
|
|
FLAG_BITWISE_OP_ASSIGN_ENUM(&=)
|
|
FLAG_BITWISE_OP_ASSIGN_ENUM(^=)
|
|
#undef FLAG_BITWISE_OP_ASSIGN_ENUM
|
|
|
|
[[nodiscard]] constexpr bool HasFlag(FlagEnum Flag) const { return ((mValue & UnsignedT(Flag)) != 0); }
|
|
[[nodiscard]] constexpr bool HasAnyFlags(const TFlags& Flags) const { return ((mValue & Flags.mValue) != 0); }
|
|
[[nodiscard]] constexpr bool HasAllFlags(const TFlags& Flags) const { return ((mValue & Flags.mValue) == Flags.mValue); }
|
|
constexpr void SetFlag(FlagEnum Flag) { mValue |= UnsignedT(Flag); }
|
|
constexpr void SetFlag(const TFlags& Flags) { mValue |= Flags.mValue; }
|
|
constexpr void ClearFlag(FlagEnum Flag) { mValue &= ~(UnsignedT(Flag)); }
|
|
constexpr void ClearFlag(const TFlags& Flags) { mValue &= ~Flags.mValue; }
|
|
|
|
constexpr void AssignFlag(FlagEnum Flag, bool Value)
|
|
{
|
|
if (Value)
|
|
SetFlag(Flag);
|
|
else
|
|
ClearFlag(Flag);
|
|
}
|
|
|
|
constexpr void Reset(FlagEnum value) { mValue = UnsignedT(value); }
|
|
constexpr void Reset(const TFlags& flags) { mValue = flags.mValue; }
|
|
|
|
[[nodiscard]] constexpr UnsignedT Value() const { return mValue; }
|
|
void Serialize(IArchive& rArc) { rArc.SerializePrimitive(mValue, SH_HexDisplay); }
|
|
};
|
|
// Note: When declaring flags for an enum class, use DECLARE_FLAGS_ENUMCLASS instead, defined below.
|
|
#define AXIO_DECLARE_FLAGS(Enum, FlagTypeName) using FlagTypeName = TFlags<Enum>;
|
|
|
|
#define AXIO_DEFINE_ENUM_OPS(EnumT) \
|
|
constexpr EnumT operator|(EnumT lhs, EnumT rhs) \
|
|
{ \
|
|
using Underlying = std::make_unsigned_t<std::underlying_type_t<EnumT>>; \
|
|
return EnumT(Underlying(lhs) | Underlying(rhs)); \
|
|
} \
|
|
constexpr EnumT operator&(EnumT lhs, EnumT rhs) \
|
|
{ \
|
|
using Underlying = std::make_unsigned_t<std::underlying_type_t<EnumT>>; \
|
|
return EnumT(Underlying(lhs) & Underlying(rhs)); \
|
|
} \
|
|
constexpr EnumT operator^(EnumT lhs, EnumT rhs) \
|
|
{ \
|
|
using Underlying = std::make_unsigned_t<std::underlying_type_t<EnumT>>; \
|
|
return EnumT(Underlying(lhs) | Underlying(rhs)); \
|
|
} \
|
|
constexpr EnumT operator~(EnumT value) \
|
|
{ \
|
|
using Underlying = std::make_unsigned_t<std::underlying_type_t<EnumT>>; \
|
|
return EnumT(~Underlying(value)); \
|
|
} \
|
|
constexpr EnumT& operator|=(EnumT& lhs, EnumT rhs) \
|
|
{ \
|
|
lhs = lhs | rhs; \
|
|
return lhs; \
|
|
} \
|
|
constexpr EnumT& operator&=(EnumT& lhs, EnumT rhs) \
|
|
{ \
|
|
lhs = lhs & rhs; \
|
|
return lhs; \
|
|
} \
|
|
constexpr EnumT& operator^=(EnumT& lhs, EnumT rhs) \
|
|
{ \
|
|
lhs = lhs ^ rhs; \
|
|
return lhs; \
|
|
} \
|
|
template <std::integral Shift> \
|
|
constexpr EnumT operator<<(EnumT lhs, Shift value) \
|
|
{ \
|
|
using Underlying = std::make_unsigned_t<std::underlying_type_t<EnumT>>; \
|
|
return EnumT(Underlying(lhs) << value); \
|
|
} \
|
|
template <std::integral Shift> \
|
|
constexpr EnumT operator>>(EnumT lhs, Shift value) \
|
|
{ \
|
|
using Underlying = std::make_unsigned_t<std::underlying_type_t<EnumT>>; \
|
|
return EnumT(Underlying(lhs) >> value); \
|
|
} \
|
|
template <std::integral Shift> \
|
|
constexpr EnumT& operator<<=(EnumT& lhs, Shift value) \
|
|
{ \
|
|
lhs = lhs << value; \
|
|
return lhs; \
|
|
} \
|
|
template <std::integral Shift> \
|
|
constexpr EnumT& operator>>=(EnumT& lhs, Shift value) \
|
|
{ \
|
|
lhs = lhs >> value; \
|
|
return lhs; \
|
|
}
|
|
|
|
#define AXIO_DECLARE_FLAGS_ENUMCLASS(Enum, FlagTypeName) \
|
|
AXIO_DECLARE_FLAGS(Enum, FlagTypeName) \
|
|
AXIO_DEFINE_ENUM_OPS(Enum)
|
|
|
|
#endif // AXIO_FLAGS_H
|
|
|