1#ifndef LIBSBX_UTILITY_ENUM_HPP_
2#define LIBSBX_UTILITY_ENUM_HPP_
9#include <libsbx/utility/string_literal.hpp>
11namespace sbx::utility {
13template<
typename Enum>
14requires (std::is_enum_v<Enum>)
15constexpr auto to_underlying(
const Enum value) -> std::underlying_type_t<Enum> {
16 return static_cast<std::underlying_type_t<Enum>
>(value);
19template<
typename Enum>
20requires (std::is_enum_v<Enum>)
21constexpr auto from_underlying(
const std::underlying_type_t<Enum> value) -> Enum {
22 return static_cast<Enum
>(value);
25template<
auto... Values>
26requires (std::is_enum_v<
decltype(Values)> && ...)
29 inline static constexpr auto values = std::array{Values...};
31 inline static constexpr auto contains(
const typename decltype(values)::value_type value)
noexcept ->
bool {
32 for (
auto entry : values) {
41 inline static constexpr auto size()
noexcept -> std::size_t {
45 inline static constexpr auto is_empty()
noexcept -> std::size_t {
54 template<
typename Type>
55 requires (std::is_enum_v<Type>)
56 inline static constexpr auto contains(
const Type value)
noexcept ->
bool {
60 inline static constexpr auto size()
noexcept -> std::size_t {
64 inline static constexpr auto is_empty()
noexcept -> std::size_t {
70template<
typename Enum>
71requires (std::is_enum_v<Enum>)
74template<
typename Enum>
75requires (std::is_enum_v<Enum>)
78template<std::
size_t Shift>
79struct bit : std::integral_constant<std::size_t, (std::size_t{1} << Shift)> { };
81template<std::size_t Shift>
82inline constexpr auto bit_v = bit<Shift>::value;
84template<typename Enum>
85requires (std::is_enum_v<Enum>)
90 using value_type = Enum;
91 using underlying_type = std::underlying_type_t<Enum>;
93 constexpr bit_field() noexcept
94 : _value{underlying_type{0}} { }
96 constexpr bit_field(const value_type value) noexcept
97 : _value{to_underlying(value)} { }
99 constexpr auto set(const value_type value) noexcept -> void {
100 _value |= static_cast<underlying_type>(value);
103 constexpr auto clear(const value_type value) noexcept -> void {
104 _value &= ~static_cast<underlying_type>(value);
107 constexpr auto has(
const value_type value)
const noexcept ->
bool {
108 return _value &
static_cast<underlying_type
>(value);
111 constexpr auto has_any() const noexcept ->
bool {
112 return _value != underlying_type{0};
115 constexpr auto has_none() const noexcept ->
bool {
116 return _value == underlying_type{0};
119 constexpr auto operator*() const noexcept -> value_type {
120 return from_underlying<value_type>(_value);
125 underlying_type _value;
129template<
typename Enum>
130requires (std::is_enum_v<Enum>)
133 std::string_view name;
136template<
typename Enum>
137requires (std::is_enum_v<Enum>)
141template<
typename Type>
142concept mapped_enum =
requires() {
143 std::is_enum_v<Type>;
147template<mapped_enum Enum>
148constexpr auto to_string(
const Enum value) -> std::string {
151 if (entry == std::ranges::end(enum_mapping<Enum>::values)) {
158template<mapped_enum Enum>
159constexpr auto from_string(
const std::string& name) -> std::optional<Enum> {
160 auto entry = std::ranges::find_if(enum_mapping<Enum>::values, [&name](
const auto& entry){
return entry.name == name; });
162 if (entry == std::ranges::end(enum_mapping<Enum>::values)) {
171template<
typename Type>
172requires (sbx::utility::is_bit_field_v<Type>)
173constexpr auto operator|(
const Type lhs,
const Type rhs) -> Type {
174 return sbx::utility::from_underlying<Type>(sbx::utility::to_underlying(lhs) | sbx::utility::to_underlying(rhs));
178template<
typename Type>
179requires (sbx::utility::is_bit_field_v<Type>)
180constexpr auto operator&(
const Type lhs,
const Type rhs) -> Type {
181 return sbx::utility::from_underlying<Type>(sbx::utility::to_underlying(lhs) & sbx::utility::to_underlying(rhs));