• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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