sandbox
Loading...
Searching...
No Matches
enum.hpp
1// SPDX-License-Identifier: MIT
2#ifndef LIBSBX_UTILITY_ENUM_HPP_
3#define LIBSBX_UTILITY_ENUM_HPP_
4
5#include <type_traits>
6#include <array>
7#include <ranges>
8#include <optional>
9#include <string_view>
10
11#include <libsbx/utility/string_literal.hpp>
12
13namespace sbx::utility {
14
15template<typename Enum>
16requires (std::is_enum_v<Enum>)
17constexpr auto to_underlying(const Enum value) -> std::underlying_type_t<Enum> {
18 return static_cast<std::underlying_type_t<Enum>>(value);
19}
20
21template<typename Enum>
22requires (std::is_enum_v<Enum>)
23constexpr auto from_underlying(const std::underlying_type_t<Enum> value) -> Enum {
24 return static_cast<Enum>(value);
25}
26
27template<auto... Values>
28requires (std::is_enum_v<decltype(Values)> && ...)
29struct enum_list {
30
31 inline static constexpr auto values = std::array{Values...};
32
33 inline static constexpr auto contains(const typename decltype(values)::value_type value) noexcept -> bool {
34 for (auto entry : values) {
35 if (entry == value) {
36 return true;
37 }
38 }
39
40 return false;
41 }
42
43 inline static constexpr auto size() noexcept -> std::size_t {
44 return values.size();
45 }
46
47 inline static constexpr auto is_empty() noexcept -> std::size_t {
48 return size() == 0u;
49 }
50
51}; // struct enum_list
52
53template<>
54struct enum_list<> {
55
56 template<typename Type>
57 requires (std::is_enum_v<Type>)
58 inline static constexpr auto contains(const Type value) noexcept -> bool {
59 return false;
60 }
61
62 inline static constexpr auto size() noexcept -> std::size_t {
63 return 0u;
64 }
65
66 inline static constexpr auto is_empty() noexcept -> std::size_t {
67 return true;
68 }
69
70}; // struct enum_list
71
72template<typename Enum>
73requires (std::is_enum_v<Enum>)
74struct is_bit_field : std::false_type { };
75
76template<typename Enum>
77requires (std::is_enum_v<Enum>)
78inline constexpr auto is_bit_field_v = is_bit_field<Enum>::value;
79
80template<std::size_t Shift>
81struct bit : std::integral_constant<std::size_t, (std::size_t{1} << Shift)> { };
82
83template<std::size_t Shift>
84inline constexpr auto bit_v = bit<Shift>::value;
85
86template<typename Enum, typename Underlying = std::underlying_type_t<Enum>>
87requires (std::is_enum_v<Enum>)
88class bit_field {
89
90public:
91
92 using value_type = Enum;
93 using underlying_type = Underlying;
94
95 constexpr bit_field() noexcept
96 : _value{underlying_type{0}} { }
97
98 constexpr bit_field(const value_type value) noexcept
99 : _value{to_underlying(value)} { }
100
101 explicit constexpr bit_field(const underlying_type value) noexcept
102 : _value{value} { }
103
104 constexpr auto set(const value_type value) noexcept -> bit_field& {
105 return *this |= value;
106 }
107
108 constexpr auto operator|=(const value_type value) noexcept -> bit_field& {
109 _value |= static_cast<underlying_type>(value);
110
111 return *this;
112 }
113
114 constexpr auto clear(const value_type value) noexcept -> void {
115 _value &= ~static_cast<underlying_type>(value);
116 }
117
118 constexpr auto override(const value_type value) noexcept -> void {
119 _value = value;
120 }
121
122 constexpr auto has(const value_type value) const noexcept -> bool {
123 return _value & static_cast<underlying_type>(value);
124 }
125
126 constexpr auto has_any() const noexcept -> bool {
127 return _value != underlying_type{0};
128 }
129
130 constexpr auto has_none() const noexcept -> bool {
131 return _value == underlying_type{0};
132 }
133
134 constexpr auto operator*() const noexcept -> value_type {
135 return from_underlying<value_type>(_value);
136 }
137
138 constexpr auto value() const -> value_type {
139 return static_cast<value_type>(_value);
140 }
141
142 constexpr auto underlying() const -> underlying_type {
143 return _value;
144 }
145
146private:
147
148 underlying_type _value;
149
150}; // class bit_field
151
152template<typename Enum>
153requires (std::is_enum_v<Enum>)
154struct entry {
155 Enum value;
156 std::string_view name;
157}; // struct entry
158
159template<typename Enum>
160requires (std::is_enum_v<Enum>)
162
163
164template<typename Type>
165concept mapped_enum = requires() {
166 std::is_enum_v<Type>;
168}; // concept mapped_enum
169
170template<mapped_enum Enum>
171constexpr auto to_string(const Enum value) -> std::string_view {
172 auto entry = std::ranges::find_if(enum_mapping<Enum>::values, [&value](const auto& entry){ return entry.value == value; });
173
174 if (entry == std::ranges::end(enum_mapping<Enum>::values)) {
175 return "<unknown>";
176 }
177
178 return entry->name;
179}
180
181template<mapped_enum Enum>
182constexpr auto from_string(const std::string_view name) -> std::optional<Enum> {
183 auto entry = std::ranges::find_if(enum_mapping<Enum>::values, [&name](const auto& entry){ return entry.name == name; });
184
185 if (entry == std::ranges::end(enum_mapping<Enum>::values)) {
186 return std::nullopt;
187 }
188
189 return entry->value;
190}
191
192} // namespace sbx::utility
193
194template<typename Type>
195requires (sbx::utility::is_bit_field_v<Type>)
196constexpr auto operator|(Type lhs, Type rhs) -> Type {
197 return sbx::utility::from_underlying<Type>(sbx::utility::to_underlying(lhs) | sbx::utility::to_underlying(rhs));
198}
199
200template<typename Type>
201requires (sbx::utility::is_bit_field_v<Type>)
202constexpr auto operator|=(Type& lhs, Type rhs) -> Type& {
203 lhs = lhs | rhs;
204
205 return lhs;
206}
207
208template<typename Type>
209requires (sbx::utility::is_bit_field_v<Type>)
210constexpr auto operator&(Type lhs, Type rhs) -> Type {
211 return sbx::utility::from_underlying<Type>(sbx::utility::to_underlying(lhs) & sbx::utility::to_underlying(rhs));
212}
213
214#endif // LIBSBX_UTILITY_ENUM_HPP_
constexpr auto operator*(basic_degree< Type > lhs, const Other rhs) noexcept -> basic_degree< Type >
Multiplies a degree value by a scalar factor.
Definition: angle.ipp:105
Definition: enum.hpp:88
Definition: enum.hpp:81
Definition: enum.hpp:154
Definition: enum.hpp:29
Definition: enum.hpp:161
Definition: enum.hpp:74