1 /*
2 * Copyright (c) 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 META_INTERFACE_DETAIL_ENUM_H
16 #define META_INTERFACE_DETAIL_ENUM_H
17
18 #include <meta/interface/detail/multi_type_any.h>
19 #include <meta/interface/enum_macros.h>
20
META_BEGIN_NAMESPACE()21 META_BEGIN_NAMESPACE()
22 namespace Internal {
23
24 template<typename Enum, size_t... Index>
25 BASE_NS::array_view<const META_NS::EnumValue> GetValues(const EnumValue<Enum>* const values, IndexSequence<Index...>)
26 {
27 static const META_NS::EnumValue arr[] { values[Index].info... };
28 return BASE_NS::array_view<const META_NS::EnumValue> { arr };
29 }
30
31 } // namespace Internal
32
33 template<typename T>
34 using EnumCompatType = BASE_NS::conditional_t<BASE_NS::is_unsigned_v<BASE_NS::underlying_type_t<T>>, uint64_t, int64_t>;
35
36 template<typename Type>
37 class EnumBase : public MultiTypeAny<Type, StaticCastConv, EnumCompatType<Type>> {
38 public:
39 explicit EnumBase(Type v = {})
40 {
41 InternalSetValue(v);
42 }
43
44 using IAny::Clone;
45 IAny::Ptr Clone(const AnyCloneOptions& options) const override;
46
47 private:
InternalSetValue(const Type & value)48 AnyReturnValue InternalSetValue(const Type& value) override
49 {
50 if (value != value_) {
51 value_ = value;
52 return AnyReturn::SUCCESS;
53 }
54 return AnyReturn::NOTHING_TO_DO;
55 }
InternalGetValue()56 const Type& InternalGetValue() const override
57 {
58 return value_;
59 }
60
61 Type value_ {};
62 };
63
64 template<typename Type>
65 class ArrayEnumBase : public ArrayMultiTypeAnyBase<Type> {
66 using Super = ArrayMultiTypeAnyBase<Type>;
67
68 public:
69 using Super::Super;
70
GetItemCompatibleTypes(CompatibilityDirection dir)71 const BASE_NS::array_view<const TypeId> GetItemCompatibleTypes(CompatibilityDirection dir) const override
72 {
73 return EnumBase<Type>::StaticGetCompatibleTypes(dir);
74 }
75
Clone(const AnyCloneOptions & options)76 IAny::Ptr Clone(const AnyCloneOptions& options) const override
77 {
78 if (options.role == TypeIdRole::ITEM) {
79 return IAny::Ptr(new EnumBase<Type>);
80 }
81 return IAny::Ptr(new ArrayEnumBase {
82 options.value == CloneValueType::COPY_VALUE ? this->value_ : typename Super::ArrayType {} });
83 }
84 };
85
86 template<typename Type>
Clone(const AnyCloneOptions & options)87 IAny::Ptr EnumBase<Type>::Clone(const AnyCloneOptions& options) const
88 {
89 if (options.role == TypeIdRole::ARRAY) {
90 return IAny::Ptr(new ArrayEnumBase<Type>());
91 }
92 return IAny::Ptr(new EnumBase { options.value == CloneValueType::COPY_VALUE ? this->value_ : Type {} });
93 }
94
95 template<typename EnumType>
96 class Enum : public IntroduceInterfaces<EnumBase<typename EnumType::Type>, IEnum> {
97 public:
98 using Super = IntroduceInterfaces<EnumBase<typename EnumType::Type>, IEnum>;
99 using Type = typename EnumType::Type;
100 using RealType = BASE_NS::underlying_type_t<Type>;
101
102 explicit Enum(Type v = EnumType::DEFAULT_VALUE)
103 {
104 InternalSetValue(v);
105 }
106
GetName()107 BASE_NS::string_view GetName() const override
108 {
109 return EnumType::NAME;
110 }
GetDescription()111 BASE_NS::string_view GetDescription() const override
112 {
113 return EnumType::DESC;
114 }
GetEnumType()115 META_NS::EnumType GetEnumType() const override
116 {
117 return EnumType::ENUM_TYPE;
118 }
GetValues()119 BASE_NS::array_view<const EnumValue> GetValues() const override
120 {
121 return Internal::GetValues(EnumType::VALUES, MakeIndexSequence<EnumType::VALUES_SIZE>());
122 }
GetValueIndex(const Type & v)123 size_t GetValueIndex(const Type& v) const
124 {
125 for (size_t i = 0; i != EnumType::VALUES_SIZE; ++i) {
126 if (v == EnumType::VALUES[i].value) {
127 return i;
128 }
129 }
130 return -1;
131 }
GetValueIndex()132 size_t GetValueIndex() const override
133 {
134 return GetValueIndex(value_);
135 }
SetValueIndex(size_t index)136 bool SetValueIndex(size_t index) override
137 {
138 if (index < EnumType::VALUES_SIZE) {
139 value_ = EnumType::VALUES[index].value;
140 return true;
141 }
142 return false;
143 }
IsValueSet(size_t index)144 bool IsValueSet(size_t index) const override
145 {
146 if (index < EnumType::VALUES_SIZE) {
147 return RealType(value_) & RealType(EnumType::VALUES[index].value);
148 }
149 return false;
150 }
FlipValue(size_t index,bool isSet)151 bool FlipValue(size_t index, bool isSet) override
152 {
153 if (EnumType::ENUM_TYPE == META_NS::EnumType::BIT_FIELD && index < EnumType::VALUES_SIZE) {
154 if (isSet) {
155 value_ = Type(RealType(value_) | RealType(EnumType::VALUES[index].value));
156 } else {
157 value_ = Type(RealType(value_) & ~RealType(EnumType::VALUES[index].value));
158 }
159 return true;
160 }
161 return false;
162 }
163
ResetValue()164 AnyReturnValue ResetValue() override
165 {
166 return InternalSetValue(EnumType::DEFAULT_VALUE);
167 }
168
169 using IAny::Clone;
170 IAny::Ptr Clone(const AnyCloneOptions& options) const override;
171
172 private:
InternalSetValue(const Type & value)173 AnyReturnValue InternalSetValue(const Type& value) override
174 {
175 if (EnumType::ENUM_TYPE == META_NS::EnumType::SINGLE_VALUE && GetValueIndex(value) == -1) {
176 return AnyReturn::INVALID_ARGUMENT;
177 }
178 if (value != value_) {
179 value_ = value;
180 return AnyReturn::SUCCESS;
181 }
182 return AnyReturn::NOTHING_TO_DO;
183 }
InternalGetValue()184 const Type& InternalGetValue() const override
185 {
186 return value_;
187 }
188
189 Type value_ { EnumType::DEFAULT_VALUE };
190 };
191
192 template<typename EnumType>
193 class ArrayEnum : public ArrayEnumBase<typename EnumType::Type> {
194 using Type = typename EnumType::Type;
195 using Super = ArrayEnumBase<Type>;
196
197 public:
198 using Super::Super;
199
GetItemCompatibleTypes(CompatibilityDirection dir)200 const BASE_NS::array_view<const TypeId> GetItemCompatibleTypes(CompatibilityDirection dir) const override
201 {
202 return Enum<EnumType>::StaticGetCompatibleTypes(dir);
203 }
204
Clone(const AnyCloneOptions & options)205 IAny::Ptr Clone(const AnyCloneOptions& options) const override
206 {
207 if (options.role == TypeIdRole::ITEM) {
208 return IAny::Ptr(new Enum<EnumType>);
209 }
210 return IAny::Ptr(new ArrayEnum {
211 options.value == CloneValueType::COPY_VALUE ? this->value_ : typename Super::ArrayType {} });
212 }
213 };
214
215 template<typename EnumType>
Clone(const AnyCloneOptions & options)216 IAny::Ptr Enum<EnumType>::Clone(const AnyCloneOptions& options) const
217 {
218 if (options.role == TypeIdRole::ARRAY) {
219 return IAny::Ptr(new ArrayEnum<EnumType>());
220 }
221 return IAny::Ptr(new Enum { options.value == CloneValueType::COPY_VALUE ? this->value_ : EnumType::DEFAULT_VALUE });
222 }
223
224 META_END_NAMESPACE()
225
226 #endif
227