1 #ifndef MAGIC_ENUM_HPP
2 #define MAGIC_ENUM_HPP
3
4 #include <array>
5 #include <exception>
6 #include <stdexcept>
7 #include <string_view>
8 #include <string>
9
10 # if defined(__clang__)
11 # define PRETTY_FUNCTION_NAME __PRETTY_FUNCTION__
12 # define ENUM_OFFSET 2
13 # elif defined(__GNUC__)
14 # define PRETTY_FUNCTION_NAME __PRETTY_FUNCTION__
15 # define ENUM_OFFSET 51
16 # elif defined(_MSC_VER)
17 # define PRETTY_FUNCTION_NAME __FUNCSIG__
18 # define ENUM_OFFSET 17
19 # endif
20 namespace OHOS {
21 namespace Sharing {
22 namespace magic_enum {
23
24 const int MAGIC_ENUM_RANGE_MAX = 1024;
25 template <typename E, E V>
get_enum_value_name()26 constexpr std::string_view get_enum_value_name()
27 {
28 std::string_view name{PRETTY_FUNCTION_NAME, sizeof(PRETTY_FUNCTION_NAME) - ENUM_OFFSET};
29 for (std::size_t i = name.size(); i > 0; --i) {
30 if (!((name[i - 1] >= '0' && name[i - 1] <= '9') || (name[i - 1] >= 'a' && name[i - 1] <= 'z') ||
31 (name[i - 1] >= 'A' && name[i - 1] <= 'Z') || (name[i - 1] == '_'))) {
32 name.remove_prefix(i);
33 break;
34 }
35 }
36 if (name.size() > 0 && ((name.front() >= 'a' && name.front() <= 'z') ||
37 (name.front() >= 'A' && name.front() <= 'Z') || (name.front() == '_'))) {
38 return name;
39 }
40 return {}; // Invalid name.
41 }
42
43 template <typename E, E V>
is_valid()44 constexpr bool is_valid()
45 {
46 return get_enum_value_name<E, V>().size() != 0;
47 }
48
49 template <int... Is>
make_integer_list_wrapper(std::integer_sequence<int, Is...>)50 constexpr auto make_integer_list_wrapper(std::integer_sequence<int, Is...>)
51 {
52 constexpr int half_size = sizeof...(Is) / 2;
53 return std::integer_sequence<int, (Is - half_size)...>();
54 }
55
56 constexpr auto test_integer_sequence_v =
57 make_integer_list_wrapper(std::make_integer_sequence<int, MAGIC_ENUM_RANGE_MAX>());
58
59 template <typename E, int... Is>
get_enum_size(std::integer_sequence<int, Is...>)60 constexpr size_t get_enum_size(std::integer_sequence<int, Is...>)
61 {
62 constexpr std::array<bool, sizeof...(Is)> valid{is_valid<E, static_cast<E>(Is)>()...};
63 constexpr std::size_t count = [](decltype((valid)) valid_) constexpr noexcept->std::size_t
64 {
65 auto count_ = std::size_t{0};
66 for (std::size_t i_ = 0; i_ < valid_.size(); ++i_) {
67 if (valid_[i_]) {
68 ++count_;
69 }
70 }
71 return count_;
72 }
73 (valid);
74 return count;
75 }
76
77 template <typename E>
78 constexpr std::size_t enum_size_v = get_enum_size<E>(test_integer_sequence_v);
79
80 template <typename E, int... Is>
get_all_valid_values(std::integer_sequence<int, Is...>)81 constexpr auto get_all_valid_values(std::integer_sequence<int, Is...>)
82 {
83 constexpr std::array<bool, sizeof...(Is)> valid{is_valid<E, static_cast<E>(Is)>()...};
84 constexpr std::array<int, sizeof...(Is)> integer_value{Is...};
85 std::array<int, enum_size_v<E>> values{};
86 for (std::size_t i = 0, v = 0; i < sizeof...(Is); ++i) {
87 if (valid[i]) {
88 values[v++] = integer_value[i];
89 }
90 }
91 return values;
92 }
93
94 template <typename E, int... Is>
get_all_valid_names(std::integer_sequence<int, Is...>)95 constexpr auto get_all_valid_names(std::integer_sequence<int, Is...>)
96 {
97 constexpr std::array<std::string_view, sizeof...(Is)> names{get_enum_value_name<E, static_cast<E>(Is)>()...};
98 std::array<std::string_view, enum_size_v<E>> valid_names{};
99 for (std::size_t i = 0, v = 0; i < names.size(); ++i) {
100 if (names[i].size() != 0) {
101 valid_names[v++] = names[i];
102 }
103 }
104 return valid_names;
105 }
106
107 template <typename E>
108 constexpr auto enum_names_v = get_all_valid_names<E>(test_integer_sequence_v);
109
110 template <typename E>
111 constexpr auto enum_values_v = get_all_valid_values<E>(test_integer_sequence_v);
112
113 template <typename E>
string2enum(const std::string_view str)114 constexpr E string2enum(const std::string_view str)
115 {
116 constexpr auto valid_names = enum_names_v<E>;
117 constexpr auto valid_values = enum_values_v<E>;
118 constexpr auto enum_size = enum_size_v<E>;
119 for (size_t i = 0; i < enum_size; ++i) {
120 if (str == valid_names[i]) {
121 return static_cast<E>(valid_values[i]);
122 }
123 }
124 return E{};
125 }
126
127 template <typename E>
enum2string(E V)128 constexpr std::string_view enum2string(E V)
129 {
130 constexpr auto valid_names = enum_names_v<E>;
131 constexpr auto valid_values = enum_values_v<E>;
132 constexpr auto enum_size = enum_size_v<E>;
133 for (size_t i = 0; i < enum_size; ++i) {
134 if (static_cast<int>(V) == valid_values[i]) {
135 return valid_names[i];
136 }
137 }
138 return "";
139 }
140
141 template <typename E>
enum_name(E value)142 constexpr auto enum_name(E value)
143 {
144 int num = static_cast<int>(value);
145 if (num > MAGIC_ENUM_RANGE_MAX / 2 || num < -(MAGIC_ENUM_RANGE_MAX / 2)) { // 2: maxnum
146 return std::to_string(static_cast<int>(value));
147 } else {
148 return std::string(enum2string<E>(value));
149 }
150 }
151
152 } // namespace magic_enum
153 } // namespace Sharing
154 } // namespace OHOS
155
156 #endif // MAGIC_ENUM_HPP