1 /*
2 * Copyright (C) 2024-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #ifndef MAGIC_ENUM_H
16 #define MAGIC_ENUM_H
17
18 #include <array>
19 #include <exception>
20 #include <stdexcept>
21 #include <string_view>
22 #include <string>
23
24 # if defined(__clang__)
25 # define PRETTY_FUNCTION_NAME __PRETTY_FUNCTION__
26 # define ENUM_OFFSET 2
27 # elif defined(__GNUC__)
28 # define PRETTY_FUNCTION_NAME __PRETTY_FUNCTION__
29 # define ENUM_OFFSET 51
30 # elif defined(_MSC_VER)
31 # define PRETTY_FUNCTION_NAME __FUNCSIG__
32 # define ENUM_OFFSET 17
33 # endif
34 namespace OHOS {
35 namespace Wifi {
36 namespace magic_enum {
37
38 const int MAGIC_ENUM_RANGE_MAX = 1024;
39 template <typename E, E V>
GetEnumValueName()40 constexpr std::string_view GetEnumValueName()
41 {
42 std::string_view name{PRETTY_FUNCTION_NAME, sizeof(PRETTY_FUNCTION_NAME) - ENUM_OFFSET};
43 for (std::size_t i = name.size(); i > 0; --i) {
44 if (!((name[i - 1] >= '0' && name[i - 1] <= '9') || (name[i - 1] >= 'a' && name[i - 1] <= 'z') ||
45 (name[i - 1] >= 'A' && name[i - 1] <= 'Z') || (name[i - 1] == '_'))) {
46 name.remove_prefix(i);
47 break;
48 }
49 }
50 if (name.size() > 0 && ((name.front() >= 'a' && name.front() <= 'z') ||
51 (name.front() >= 'A' && name.front() <= 'Z') || (name.front() == '_'))) {
52 return name;
53 }
54 return {}; // Invalid name.
55 }
56
57 template <typename E, E V>
IsValid()58 constexpr bool IsValid()
59 {
60 return GetEnumValueName<E, V>().size() != 0;
61 }
62
63 template <int... Is>
MakeIntegerListWrapper(std::integer_sequence<int,Is...>)64 constexpr auto MakeIntegerListWrapper(std::integer_sequence<int, Is...>)
65 {
66 constexpr int halfSize = static_cast<int>(sizeof...(Is) / 2);
67 return std::integer_sequence<int, (Is - halfSize)...>();
68 }
69
70 constexpr auto TEST_INTEGER_SEQUENCE_V =
71 MakeIntegerListWrapper(std::make_integer_sequence<int, MAGIC_ENUM_RANGE_MAX>());
72
73 template <typename E, int... Is>
GetEnumSize(std::integer_sequence<int,Is...>)74 constexpr size_t GetEnumSize(std::integer_sequence<int, Is...>)
75 {
76 constexpr std::array<bool, sizeof...(Is)> valid{IsValid<E, static_cast<E>(Is)>()...};
77 constexpr std::size_t count = [](decltype((valid)) validValue) constexpr noexcept->std::size_t {
78 auto nSize = std::size_t{0};
79 for (std::size_t index = 0; index < validValue.size(); ++index) {
80 if (validValue[index]) {
81 ++nSize;
82 }
83 }
84 return nSize;
85 }
86 (valid);
87 return count;
88 }
89
90 template <typename E>
91 constexpr std::size_t ENUM_SIZE_V = GetEnumSize<E>(TEST_INTEGER_SEQUENCE_V);
92
93 template <typename E, int... Is>
GetAllValidValues(std::integer_sequence<int,Is...>)94 constexpr auto GetAllValidValues(std::integer_sequence<int, Is...>)
95 {
96 constexpr std::array<bool, sizeof...(Is)> valid{IsValid<E, static_cast<E>(Is)>()...};
97 constexpr std::array<int, sizeof...(Is)> integerValue{Is...};
98 std::array<int, ENUM_SIZE_V<E>> values{};
99 for (std::size_t i = 0, v = 0; i < sizeof...(Is); ++i) {
100 if (valid[i]) {
101 values[v++] = integerValue[i];
102 }
103 }
104 return values;
105 }
106
107 template <typename E, int... Is>
GetAllValidNames(std::integer_sequence<int,Is...>)108 constexpr auto GetAllValidNames(std::integer_sequence<int, Is...>)
109 {
110 constexpr std::array<std::string_view, sizeof...(Is)> names{GetEnumValueName<E, static_cast<E>(Is)>()...};
111 std::array<std::string_view, ENUM_SIZE_V<E>> valid_names{};
112 for (std::size_t i = 0, v = 0; i < names.size(); ++i) {
113 if (names[i].size() != 0) {
114 valid_names[v++] = names[i];
115 }
116 }
117 return valid_names;
118 }
119
120 template <typename E>
121 constexpr auto ENUM_NAMES_V = GetAllValidNames<E>(TEST_INTEGER_SEQUENCE_V);
122
123 template <typename E>
124 constexpr auto ENUM_VALUES_V = GetAllValidValues<E>(TEST_INTEGER_SEQUENCE_V);
125
126 template <typename E>
Enum2string(E V)127 constexpr std::string_view Enum2string(E V)
128 {
129 constexpr auto validNames = ENUM_NAMES_V<E>;
130 constexpr auto validValues = ENUM_VALUES_V<E>;
131 constexpr auto enumSize = ENUM_SIZE_V<E>;
132 for (size_t i = 0; i < enumSize; ++i) {
133 if (static_cast<int>(V) == validValues[i]) {
134 return validNames[i];
135 }
136 }
137 return "";
138 }
139
140 template <typename E>
Enum2Name(E value)141 constexpr auto Enum2Name(E value)
142 {
143 int num = static_cast<int>(value);
144 if (num > MAGIC_ENUM_RANGE_MAX / 2 || num < -(MAGIC_ENUM_RANGE_MAX / 2)) { // 2: maxnum
145 return std::to_string(static_cast<int>(value));
146 } else {
147 return std::string(Enum2string<E>(value));
148 }
149 }
150
151 } // namespace magic_enum
152 } // namespace Wifi
153 } // namespace OHOS
154
155 #endif