AUI Framework  develop
Cross-platform base for C++ UI apps
Loading...
Searching...
No Matches
AEnumerate.h
1/*
2 * AUI Framework - Declarative UI toolkit for modern C++20
3 * Copyright (C) 2020-2024 Alex2772 and Contributors
4 *
5 * SPDX-License-Identifier: MPL-2.0
6 *
7 * This Source Code Form is subject to the terms of the Mozilla Public
8 * License, v. 2.0. If a copy of the MPL was not distributed with this
9 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 */
11
12//
13// Created by alex2 on 6/24/2021.
14//
15
16#pragma once
17
18#include <array>
19#include <type_traits>
20#include <AUI/Common/AString.h>
21#include <AUI/Common/AMap.h>
22#include <AUI/Traits/types.h>
23#include <fmt/format.h>
24
25
26//NOLINTBEGIN(modernize-*,cppcoreguidelines-macro-usage,bugprone-macro-parentheses)
27
28namespace aui::enumerate::basic {
29 template<typename enum_t>
30 struct ValueToName {
31 template<enum_t value>
32 static AString name() {
33#if AUI_COMPILER_MSVC
34 AString s = __FUNCSIG__;
35 AString::iterator end = s.begin() + s.rfind('>');
36 AString::iterator begin = (std::find_if(std::make_reverse_iterator(end), s.rend(), [](wchar_t c) {
37 return c == ':' || c == '<';
38 })).base();
39
40 AString result(begin, end);
41#else
42 AString s = __PRETTY_FUNCTION__;
43#if AUI_COMPILER_CLANG
44 auto end = s.rfind(']');
45#else
46 auto end = s.rfind(';');
47#endif
48 size_t begin = s.rfind("value =", end);
49 if (begin == AString::NPOS) {
50 begin = s.rfind('[', end) + 1;
51 } else {
52 begin += 8;
53 }
54 AString result = {s.begin() + begin, s.begin() + end};
55
56
57 for (size_t p; (p = result.find("::")) != AString::NPOS;) {
58 result = result.substr(p + 2);
59 }
60
61#endif
62 return result;
63 }
64 };
65};
66
67namespace aui::enumerate {
68 template<typename enum_t>
69 struct ValueToName: basic::ValueToName<enum_t> {};
70}
71
72
78template<typename enum_t>
80private:
81 struct enum_less {
82 constexpr bool operator()(enum_t l, enum_t r) const {
83 return static_cast<std::underlying_type_t<enum_t>>(l) < static_cast<std::underlying_type_t<enum_t>>(r);
84 }
85 };
86
87public:
88 static_assert(std::is_enum_v<enum_t>, "AEnumerate accepts only enums");
89
90 template<enum_t... values>
91 struct Values {
92
93 };
94
102 template<enum_t value>
105 }
106
112
117
121 static enum_t byName(const AString& name) {
122 if (auto c = nameToValueMap().contains(name)) {
123 return c->second;
124 }
125 if (auto c = nameToValueMap().contains(name.uppercase())) {
126 return c->second;
127 }
128 throw AException("unknown enum value: \"{}\""_format(name));
129 }
130
134 static const AString& toName(enum_t value) {
135 if (auto c = valueToNameMap().contains(value)) {
136 return c->second;
137 }
138 throw AException("unknown enum value: \"(int){}\""_format((std::underlying_type_t<enum_t>)value));
139 }
140
141private:
142 template<enum_t... values>
143 static const AMap<AString, enum_t>& mapValueByName(const Values<values...>& v) {
144 static AMap<AString, enum_t> map = {
145 {valueName<values>(), values}...
146 };
147 return map;
148 }
149 template<enum_t... values>
150 static const AMap<enum_t, AString, enum_less>& mapNameByValue(const Values<values...>& v) {
151 static AMap<enum_t, AString, enum_less> map = {
152 {values, valueName<values>() }...
153 };
154 return map;
155 }
156};
157
158template<typename enum_t>
160
161template<typename enum_t>
163 static_assert(aui::is_complete<AEnumerateAllValues<enum_t>>, "AUI_ENUM_VALUES is not defined for this enum type");
165
166 return mapValueByName(v);
167}
168
169namespace aui::enumerate {
175 template<typename enum_t> requires aui::is_complete<AEnumerateAllValues<enum_t>>
176 inline constexpr auto ALL_VALUES = []<auto... values>(typename AEnumerate<enum_t>::template Values<values...>) {
177 constexpr enum_t ITEMS[] = {values...};
178 return std::to_array(ITEMS);
180}
181
182template<typename enum_t>
184 static_assert(aui::is_complete<AEnumerateAllValues<enum_t>>, "AUI_ENUM_VALUES is not defined for this enum type");
186
187 return mapNameByValue(v);
188}
189
208#define AUI_ENUM_VALUES(enum_t, ...) template<> \
209struct AEnumerateAllValues<enum_t>{ \
210 static inline constexpr AEnumerate<enum_t>::Values<__VA_ARGS__> get() {return {}; } \
211}; \
212namespace std { inline AString to_wstring(enum_t v) { return AEnumerate<enum_t>::valueToNameMap().optional(v).valueOr("<unknown enum value {}>"_format(int(v))); } } \
213inline std::ostream& operator<<(std::ostream& o, enum_t v) { return o << std::to_wstring(v); }
214
215template <typename T> struct fmt::formatter<T, char, std::enable_if_t<aui::is_complete<AEnumerateAllValues<T>>>>: formatter<std::string> {
216 // parse is inherited from formatter<string_view>.
217 template <typename FormatContext>
218 auto format(T c, FormatContext& ctx) const {
219 return formatter<string_view>::format(AEnumerate<T>::valueToNameMap()[c].toStdString(), ctx);
220 }
221};
222
223
224
225#define AUI_ENUM_FLAG(name) enum class name: int; \
226 constexpr inline name operator|(name a, name b) {return static_cast<name>(static_cast<int>(a) | static_cast<int>(b));} \
227 constexpr inline name operator&(name a, name b) {return static_cast<name>(static_cast<int>(a) & static_cast<int>(b));} \
228 constexpr inline name operator^(name a, name b) {return static_cast<name>(static_cast<int>(a) ^ static_cast<int>(b));} \
229 constexpr inline name operator|=(name& a, name b) {return a = static_cast<name>(static_cast<int>(a) | static_cast<int>(b));} \
230 constexpr inline name operator&=(name& a, name b) {return a = static_cast<name>(static_cast<int>(a) & static_cast<int>(b));} \
231 constexpr inline name operator^=(name& a, name b) {return a = static_cast<name>(static_cast<int>(a) ^ static_cast<int>(b));} \
232 constexpr inline name operator~(const name& a) {return static_cast<name>(~static_cast<int>(a));} \
233 constexpr inline bool operator!(const name& a) {return a == static_cast<name>(0);} \
234 \
235 constexpr inline bool operator&&(const name& a, bool v) {return static_cast<int>(a) && v;} \
236 constexpr inline bool operator||(const name& a, bool v) {return static_cast<int>(a) || v;} \
237\
238 enum class name: int
239
240#define AUI_ENUM_INT(name) enum class name: int; \
241 constexpr inline bool operator<(name a, name b) {return static_cast<int>(a) < static_cast<int>(b);} \
242 constexpr inline bool operator>(name a, name b) {return static_cast<int>(a) > static_cast<int>(b);} \
243 enum class name: int
244
245//NOLINTEND(modernize-*,cppcoreguidelines-macro-usage,bugprone-macro-parentheses)
Enum trait to transform enum to name, name to enum, list all enums and vise versa.
Definition AEnumerate.h:79
static const AMap< AString, enum_t > & nameToValueMap()
Get runtime name to enum value mapping.
Definition AEnumerate.h:162
static AString valueName()
Maps compile-time specified enum value to name.
Definition AEnumerate.h:103
static enum_t byName(const AString &name)
Map runtime name to enum value. Transforms name to uppercase as a fallback. Throws an exception if no...
Definition AEnumerate.h:121
static const AMap< enum_t, AString, enum_less > & valueToNameMap()
Map runtime enum value to name.
Definition AEnumerate.h:183
static const AString & toName(enum_t value)
Map runtime enum value to name. Throws an exception if no such value.
Definition AEnumerate.h:134
Abstract AUI exception.
Definition AException.h:28
A std::map with AUI extensions.
Definition AMap.h:218
Represents a Unicode character string.
Definition AString.h:37
constexpr auto ALL_VALUES
constexpr std::array of all possible enum values is the order they've been passed to AUI_ENUM_VALUES.
Definition AEnumerate.h:176
constexpr bool is_complete
Determines whether T is complete or not.
Definition types.h:23
Definition AEnumerate.h:159
Definition AEnumerate.h:91
Definition AEnumerate.h:69
Definition AEnumerate.h:30