/* * Copyright (c) 2022, Ali Mohammad Pur * Copyright (c) 2022, Linus Groh * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include namespace AK { template struct ArbitrarySizedEnum : public T { using T::T; consteval ArbitrarySizedEnum(T v) : T(v) { } constexpr ArbitrarySizedEnum(T v, Badge>) : T(v) { } template [[nodiscard]] consteval ArbitrarySizedEnum operator<<(X other) const { return T(this->value() << other); } template constexpr ArbitrarySizedEnum& operator<<=(X other) { this->value() <<= other; return *this; } template [[nodiscard]] consteval ArbitrarySizedEnum operator>>(X other) const { return T(this->value() >> other); } template constexpr ArbitrarySizedEnum& operator>>=(X other) { this->value() >>= other; return *this; } template [[nodiscard]] constexpr bool operator==(X other) const { return this->value() == T(other); } [[nodiscard]] constexpr bool operator==(ArbitrarySizedEnum const& other) const { return this->value() == other.value(); } // NOTE: The following operators mirror AK_ENUM_BITWISE_OPERATORS. [[nodiscard]] constexpr ArbitrarySizedEnum operator|(ArbitrarySizedEnum const& other) const { return { T(this->value() | other.value()), {} }; } [[nodiscard]] constexpr ArbitrarySizedEnum operator&(ArbitrarySizedEnum const& other) const { return { T(this->value() & other.value()), {} }; } [[nodiscard]] constexpr ArbitrarySizedEnum operator^(ArbitrarySizedEnum const& other) const { return { T(this->value() ^ other.value()), {} }; } [[nodiscard]] constexpr ArbitrarySizedEnum operator~() const { return { T(~this->value()), {} }; } constexpr ArbitrarySizedEnum& operator|=(ArbitrarySizedEnum const& other) { this->value() |= other.value(); return *this; } constexpr ArbitrarySizedEnum& operator&=(ArbitrarySizedEnum const& other) { this->value() &= other.value(); return *this; } constexpr ArbitrarySizedEnum& operator^=(ArbitrarySizedEnum const& other) { this->value() ^= other.value(); return *this; } [[nodiscard]] constexpr bool has_flag(ArbitrarySizedEnum const& mask) const { return (*this & mask) == mask; } [[nodiscard]] constexpr bool has_any_flag(ArbitrarySizedEnum const& mask) const { return (*this & mask) != 0u; } }; #define AK_MAKE_ARBITRARY_SIZED_ENUM(EnumName, T, ...) \ namespace EnumName { \ using EnumName = ArbitrarySizedEnum>; \ using Type = EnumName; \ using UnderlyingType = T; \ inline constexpr static EnumName __VA_ARGS__; \ } } #if USING_AK_GLOBALLY using AK::ArbitrarySizedEnum; #endif