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