sandbox
Loading...
Searching...
No Matches
enum.hpp
1#ifndef LIBSBX_UTILITY_ENUM_HPP_
2#define LIBSBX_UTILITY_ENUM_HPP_
3
4#include <type_traits>
5#include <array>
6#include <ranges>
7#include <optional>
8
9#include <libsbx/utility/string_literal.hpp>
10
11namespace sbx::utility {
12
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);
17}
18
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);
23}
24
25template<auto... Values>
26requires (std::is_enum_v<decltype(Values)> && ...)
27struct enum_list {
28
29 inline static constexpr auto values = std::array{Values...};
30
31 inline static constexpr auto contains(const typename decltype(values)::value_type value) noexcept -> bool {
32 for (auto entry : values) {
33 if (entry == value) {
34 return true;
35 }
36 }
37
38 return false;
39 }
40
41 inline static constexpr auto size() noexcept -> std::size_t {
42 return values.size();
43 }
44
45 inline static constexpr auto is_empty() noexcept -> std::size_t {
46 return size() == 0u;
47 }
48
49}; // struct enum_list
50
51template<>
52struct enum_list<> {
53
54 template<typename Type>
55 requires (std::is_enum_v<Type>)
56 inline static constexpr auto contains(const Type value) noexcept -> bool {
57 return false;
58 }
59
60 inline static constexpr auto size() noexcept -> std::size_t {
61 return 0u;
62 }
63
64 inline static constexpr auto is_empty() noexcept -> std::size_t {
65 return true;
66 }
67
68}; // struct enum_list
69
70template<typename Enum>
71requires (std::is_enum_v<Enum>)
72struct is_bit_field : std::false_type { };
73
74template<typename Enum>
75requires (std::is_enum_v<Enum>)
76inline constexpr auto is_bit_field_v = is_bit_field<Enum>::value;
77
78template<std::size_t Shift>
79struct bit : std::integral_constant<std::size_t, (std::size_t{1} << Shift)> { };
80
81template<std::size_t Shift>
82inline constexpr auto bit_v = bit<Shift>::value;
83
84template<typename Enum>
85requires (std::is_enum_v<Enum>)
86class bit_field {
87
88public:
89
90 using value_type = Enum;
91 using underlying_type = std::underlying_type_t<Enum>;
92
93 constexpr bit_field() noexcept
94 : _value{underlying_type{0}} { }
95
96 constexpr bit_field(const value_type value) noexcept
97 : _value{to_underlying(value)} { }
98
99 constexpr auto set(const value_type value) noexcept -> void {
100 _value |= static_cast<underlying_type>(value);
101 }
102
103 constexpr auto clear(const value_type value) noexcept -> void {
104 _value &= ~static_cast<underlying_type>(value);
105 }
106
107 constexpr auto has(const value_type value) const noexcept -> bool {
108 return _value & static_cast<underlying_type>(value);
109 }
110
111 constexpr auto has_any() const noexcept -> bool {
112 return _value != underlying_type{0};
113 }
114
115 constexpr auto has_none() const noexcept -> bool {
116 return _value == underlying_type{0};
117 }
118
119 constexpr auto operator*() const noexcept -> value_type {
120 return from_underlying<value_type>(_value);
121 }
122
123private:
124
125 underlying_type _value;
126
127}; // class bit_field
128
129template<typename Enum>
130requires (std::is_enum_v<Enum>)
131struct entry {
132 Enum value;
133 std::string_view name;
134}; // struct entry
135
136template<typename Enum>
137requires (std::is_enum_v<Enum>)
139
140
141template<typename Type>
142concept mapped_enum = requires() {
143 std::is_enum_v<Type>;
145}; // concept mapped_enum
146
147template<mapped_enum Enum>
148constexpr auto to_string(const Enum value) -> std::string {
149 auto entry = std::ranges::find_if(enum_mapping<Enum>::values, [&value](const auto& entry){ return entry.value == value; });
150
151 if (entry == std::ranges::end(enum_mapping<Enum>::values)) {
152 return "<unknown>";
153 }
154
155 return entry->name;
156}
157
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; });
161
162 if (entry == std::ranges::end(enum_mapping<Enum>::values)) {
163 return std::nullopt;
164 }
165
166 return entry->value;
167}
168
169} // namespace sbx::utility
170
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));
175}
176
177
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));
182}
183
184#endif // LIBSBX_UTILITY_ENUM_HPP_
Definition: enum.hpp:79
Definition: enum.hpp:131
Definition: enum.hpp:27
Definition: enum.hpp:138
Definition: enum.hpp:72