diff options
author | Linus Groh <mail@linusgroh.de> | 2022-03-27 12:48:12 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-03-27 18:54:56 +0200 |
commit | 22308e52cfd9e0064838e8e28f195807516e2d2c (patch) | |
tree | 7a6ca75a8af17dcf5bae864fe486007b40b1e1b2 /AK | |
parent | 8b2361e36259336e45e85c3859b3f513d7ddfaba (diff) | |
download | serenity-22308e52cfd9e0064838e8e28f195807516e2d2c.zip |
AK: Add an ArbitrarySizedEnum template
This is an enum-like type that works with arbitrary sized storage > u64,
which is the limit for a regular enum class - which limits it to 64
members when needing bit field behavior.
Co-authored-by: Ali Mohammad Pur <mpfard@serenityos.org>
Diffstat (limited to 'AK')
-rw-r--r-- | AK/ArbitrarySizedEnum.h | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/AK/ArbitrarySizedEnum.h b/AK/ArbitrarySizedEnum.h new file mode 100644 index 0000000000..3e74086612 --- /dev/null +++ b/AK/ArbitrarySizedEnum.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2022, Ali Mohammad Pur <mpfard@serenityos.org> + * Copyright (c) 2022, Linus Groh <linusg@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/DistinctNumeric.h> + +namespace AK { + +template<typename T> +struct ArbitrarySizedEnum : public T { + using T::T; + + consteval ArbitrarySizedEnum(T v) + : T(v) + { + } + + constexpr ArbitrarySizedEnum(T v, Badge<ArbitrarySizedEnum<T>>) + : T(v) + { + } + + template<Integral X> + [[nodiscard]] consteval ArbitrarySizedEnum<T> operator<<(X other) const + { + return T(this->value() << other); + } + + template<Integral X> + constexpr ArbitrarySizedEnum<T>& operator<<=(X other) + { + this->value() <<= other; + return *this; + } + + template<Integral X> + [[nodiscard]] consteval ArbitrarySizedEnum<T> operator>>(X other) const + { + return T(this->value() >> other); + } + + template<Integral X> + constexpr ArbitrarySizedEnum<T>& operator>>=(X other) + { + this->value() >>= other; + return *this; + } + + template<Integral X> + [[nodiscard]] constexpr bool operator==(X other) const + { + return this->value() == T(other); + } + + [[nodiscard]] constexpr bool operator==(ArbitrarySizedEnum<T> const& other) const + { + return this->value() == other.value(); + } + + // NOTE: The following operators mirror AK_ENUM_BITWISE_OPERATORS. + + [[nodiscard]] constexpr ArbitrarySizedEnum<T> operator|(ArbitrarySizedEnum<T> const& other) const + { + return { T(this->value() | other.value()), {} }; + } + + [[nodiscard]] constexpr ArbitrarySizedEnum<T> operator&(ArbitrarySizedEnum<T> const& other) const + { + return { T(this->value() & other.value()), {} }; + } + + [[nodiscard]] constexpr ArbitrarySizedEnum<T> operator^(ArbitrarySizedEnum<T> const& other) const + { + return { T(this->value() ^ other.value()), {} }; + } + + [[nodiscard]] constexpr ArbitrarySizedEnum<T> operator~() const + { + return { T(~this->value()), {} }; + } + + constexpr ArbitrarySizedEnum<T>& operator|=(ArbitrarySizedEnum<T> const& other) + { + this->value() |= other.value(); + return *this; + } + + constexpr ArbitrarySizedEnum<T>& operator&=(ArbitrarySizedEnum<T> const& other) + { + this->value() &= other.value(); + return *this; + } + + constexpr ArbitrarySizedEnum<T>& operator^=(ArbitrarySizedEnum<T> const& other) + { + this->value() ^= other.value(); + return *this; + } + + [[nodiscard]] constexpr bool has_flag(ArbitrarySizedEnum<T> const& mask) const + { + return (*this & mask) == mask; + } + + [[nodiscard]] constexpr bool has_any_flag(ArbitrarySizedEnum<T> const& mask) const + { + return (*this & mask) != 0u; + } +}; + +#define AK_MAKE_ARBITRARY_SIZED_ENUM(EnumName, T, ...) \ + namespace EnumName { \ + using EnumName = ArbitrarySizedEnum<DistinctNumeric<T, struct __##EnumName##Tag, \ + false, true, false, false, false, false>>; \ + using Type = EnumName; \ + using UnderlyingType = T; \ + inline constexpr static EnumName __VA_ARGS__; \ + } + +} + +using AK::ArbitrarySizedEnum; |