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 halfSize = static_cast<int>(sizeof...(Is) / 2);
53 return std::integer_sequence<int, (Is - halfSize)...>();
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 auto count_ = std::size_t{0};
65 for (std::size_t i_ = 0; i_ < valid_.size(); ++i_) {
66 if (valid_[i_]) {
67 ++count_;
68 }
69 }
70 return count_;
71 }(valid);
72 return count;
73 }
74
75 template <typename E>
76 constexpr std::size_t enum_size_v = get_enum_size<E>(test_integer_sequence_v);
77
78 template <typename E, int... Is>
get_all_valid_values(std::integer_sequence<int,Is...>)79 constexpr auto get_all_valid_values(std::integer_sequence<int, Is...>)
80 {
81 constexpr std::array<bool, sizeof...(Is)> valid{is_valid<E, static_cast<E>(Is)>()...};
82 constexpr std::array<int, sizeof...(Is)> integer_value{Is...};
83 std::array<int, enum_size_v<E>> values{};
84 for (std::size_t i = 0, v = 0; i < sizeof...(Is); ++i) {
85 if (valid[i]) {
86 values[v++] = integer_value[i];
87 }
88 }
89 return values;
90 }
91
92 template <typename E, int... Is>
get_all_valid_names(std::integer_sequence<int,Is...>)93 constexpr auto get_all_valid_names(std::integer_sequence<int, Is...>)
94 {
95 constexpr std::array<std::string_view, sizeof...(Is)> names{get_enum_value_name<E, static_cast<E>(Is)>()...};
96 std::array<std::string_view, enum_size_v<E>> valid_names{};
97 for (std::size_t i = 0, v = 0; i < names.size(); ++i) {
98 if (names[i].size() != 0) {
99 valid_names[v++] = names[i];
100 }
101 }
102 return valid_names;
103 }
104
105 template <typename E>
106 constexpr auto enum_names_v = get_all_valid_names<E>(test_integer_sequence_v);
107
108 template <typename E>
109 constexpr auto enum_values_v = get_all_valid_values<E>(test_integer_sequence_v);
110
111 template <typename E>
string2enum(const std::string_view str)112 constexpr E string2enum(const std::string_view str)
113 {
114 constexpr auto valid_names = enum_names_v<E>;
115 constexpr auto valid_values = enum_values_v<E>;
116 constexpr auto enum_size = enum_size_v<E>;
117 for (size_t i = 0; i < enum_size; ++i) {
118 if (str == valid_names[i]) {
119 return static_cast<E>(valid_values[i]);
120 }
121 }
122 return E{};
123 }
124
125 template <typename E>
enum2string(E V)126 constexpr std::string_view enum2string(E V)
127 {
128 constexpr auto valid_names = enum_names_v<E>;
129 constexpr auto valid_values = enum_values_v<E>;
130 constexpr auto enum_size = enum_size_v<E>;
131 for (size_t i = 0; i < enum_size; ++i) {
132 if (static_cast<int>(V) == valid_values[i]) {
133 return valid_names[i];
134 }
135 }
136 return "";
137 }
138
139 template <typename E>
enum_name(E value)140 constexpr auto enum_name(E value)
141 {
142 int num = static_cast<int>(value);
143 if (num > MAGIC_ENUM_RANGE_MAX / 2 || num < -(MAGIC_ENUM_RANGE_MAX / 2)) { // 2: maxnum
144 return std::to_string(static_cast<int>(value));
145 } else {
146 return std::string(enum2string<E>(value));
147 }
148 }
149
150 } // namespace magic_enum
151 } // namespace Sharing
152 } // namespace OHOS
153
154 #endif // MAGIC_ENUM_HPP