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_ARRAY_PROPERTY_H
17 #define META_INTERFACE_DETAIL_ARRAY_PROPERTY_H
18
19 #include <meta/interface/detail/any.h>
20 #include <meta/interface/detail/property.h>
21
META_BEGIN_NAMESPACE()22 META_BEGIN_NAMESPACE()
23
24 template<typename Base>
25 class ConstTypelessArrayPropertyInterfaceImpl : public Base {
26 public:
27 using IndexType = IArrayAny::IndexType;
28
29 template<typename Prop>
30 explicit ConstTypelessArrayPropertyInterfaceImpl(Prop* p) : Base(p)
31 {}
32
33 IndexType GetSize() const
34 {
35 if (auto arr = interface_cast<IArrayAny>(&this->GetValueAny())) {
36 return arr->GetSize();
37 }
38 return {};
39 }
40 AnyReturnValue GetAnyAt(IndexType index, IAny& any) const
41 {
42 if (auto arr = interface_cast<IArrayAny>(&this->GetValueAny())) {
43 return arr->GetAnyAt(index, any);
44 }
45 return AnyReturn::INCOMPATIBLE_TYPE;
46 }
47 };
48
49 using ConstTypelessArrayPropertyInterface = ConstTypelessArrayPropertyInterfaceImpl<ConstTypelessPropertyInterface>;
50
51 class TypelessArrayPropertyInterface : public ConstTypelessArrayPropertyInterfaceImpl<TypelessPropertyInterface> {
52 public:
53 using PropertyType = IProperty*;
54 using IndexType = IArrayAny::IndexType;
55
TypelessArrayPropertyInterface(PropertyType p)56 TypelessArrayPropertyInterface(PropertyType p)
57 : ConstTypelessArrayPropertyInterfaceImpl<TypelessPropertyInterface>(p)
58 {}
59
SetAnyAt(IndexType index,const IAny & v)60 AnyReturnValue SetAnyAt(IndexType index, const IAny& v)
61 {
62 if (auto c = this->GetValueAny().Clone(true)) {
63 if (auto arr = interface_cast<IArrayAny>(c)) {
64 arr->SetAnyAt(index, v);
65 return this->SetValueAny(*arr);
66 }
67 }
68 return AnyReturn::INCOMPATIBLE_TYPE;
69 }
AddAny(const IAny & v)70 AnyReturnValue AddAny(const IAny& v)
71 {
72 return InsertAnyAt(-1, v);
73 }
InsertAnyAt(IndexType index,const IAny & v)74 AnyReturnValue InsertAnyAt(IndexType index, const IAny& v)
75 {
76 if (auto c = this->GetValueAny().Clone(true)) {
77 if (auto arr = interface_cast<IArrayAny>(c)) {
78 arr->InsertAnyAt(index, v);
79 return this->SetValueAny(*arr);
80 }
81 }
82 return AnyReturn::INCOMPATIBLE_TYPE;
83 }
RemoveAt(IndexType index)84 bool RemoveAt(IndexType index)
85 {
86 if (auto c = this->GetValueAny().Clone(true)) {
87 if (auto arr = interface_cast<IArrayAny>(c)) {
88 arr->RemoveAt(index);
89 return this->SetValueAny(*arr);
90 }
91 }
92 return false;
93 }
94 };
95
96 template<typename Type>
97 using ArrayPropertyBaseType = BASE_NS::conditional_t<BASE_NS::is_const_v<Type>, ConstTypelessArrayPropertyInterface,
98 TypelessArrayPropertyInterface>;
99
100 template<typename Type>
101 class ArrayPropertyInterface : public ArrayPropertyBaseType<Type> {
102 using Super = ArrayPropertyBaseType<Type>;
103
104 public:
105 using ValueType = BASE_NS::remove_const_t<Type>;
106 using PropertyType = typename PropertyBaseType<Type>::PropertyType;
107 using IndexType = IArrayAny::IndexType;
108
ArrayPropertyInterface(PropertyType p)109 explicit ArrayPropertyInterface(PropertyType p) : Super(p) {}
110
GetValueAt(IndexType index)111 ValueType GetValueAt(IndexType index) const
112 {
113 Any<ValueType> any;
114 if (auto arr = interface_cast<IArrayAny>(&this->GetValueAny())) {
115 arr->GetAnyAt(index, any);
116 }
117 return any.InternalGetValue();
118 }
SetValueAt(IndexType index,const Type & v)119 bool SetValueAt(IndexType index, const Type& v)
120 {
121 BASE_NS::vector<ValueType> vec;
122 if (this->GetValueAny().GetValue(vec)) {
123 if (index < vec.size()) {
124 vec[index] = v;
125 return this->SetValueAny(ArrayAny<ValueType>(BASE_NS::move(vec)));
126 }
127 }
128 return false;
129 }
AddValue(const Type & v)130 bool AddValue(const Type& v)
131 {
132 return InsertValueAt(-1, v);
133 }
InsertValueAt(IndexType index,const Type & v)134 bool InsertValueAt(IndexType index, const Type& v)
135 {
136 BASE_NS::vector<ValueType> vec;
137 if (this->GetValueAny().GetValue(vec)) {
138 index = index < vec.size() ? index : vec.size();
139 vec.insert(vec.begin() + index, v);
140 return this->SetValueAny(ArrayAny<ValueType>(BASE_NS::move(vec)));
141 }
142 return false;
143 }
GetDefaultValue()144 BASE_NS::vector<ValueType> GetDefaultValue() const
145 {
146 BASE_NS::vector<ValueType> v;
147 this->GetDefaultValueAny().GetValue(v);
148 return v;
149 }
150
SetDefaultValue(BASE_NS::array_view<const ValueType> value)151 AnyReturnValue SetDefaultValue(BASE_NS::array_view<const ValueType> value)
152 {
153 return this->SetDefaultValueAny(ArrayAny<ValueType>(value));
154 }
155
156 template<typename T, typename = BASE_NS::enable_if_t<BASE_NS::is_same_v<T, ValueType>>>
SetDefaultValue(BASE_NS::vector<T> value)157 AnyReturnValue SetDefaultValue(BASE_NS::vector<T> value)
158 {
159 return this->SetDefaultValueAny(ArrayAny<ValueType>(BASE_NS::move(value)));
160 }
161
SetDefaultValue(BASE_NS::vector<ValueType> value,bool resetToDefault)162 AnyReturnValue SetDefaultValue(BASE_NS::vector<ValueType> value, bool resetToDefault)
163 {
164 auto ret = this->SetDefaultValueAny(ArrayAny<ValueType>(BASE_NS::move(value)));
165 if (resetToDefault && ret) {
166 this->ResetValue();
167 }
168 return ret;
169 }
170
GetValue()171 BASE_NS::vector<ValueType> GetValue() const
172 {
173 BASE_NS::vector<ValueType> v {};
174 this->GetValueAny().GetValue(v);
175 return v;
176 }
177
SetValue(BASE_NS::array_view<const ValueType> value)178 AnyReturnValue SetValue(BASE_NS::array_view<const ValueType> value)
179 {
180 return this->SetValueAny(ArrayAny<ValueType>(value));
181 }
182
183 template<typename T, typename = BASE_NS::enable_if_t<BASE_NS::is_same_v<T, ValueType>>>
SetValue(BASE_NS::vector<T> value)184 AnyReturnValue SetValue(BASE_NS::vector<T> value)
185 {
186 return this->SetValueAny(ArrayAny<ValueType>(BASE_NS::move(value)));
187 }
188
FindFirstValueOf(const Type & v)189 IndexType FindFirstValueOf(const Type& v) const
190 {
191 for (IndexType i = 0; i != this->GetSize(); ++i) {
192 if (GetValueAt(i) == v) {
193 return i;
194 }
195 }
196 return -1;
197 }
198 };
199
200 template<typename Type>
201 class TypedArrayPropertyLock final : public ArrayPropertyInterface<Type> {
202 using PropertyType = typename ArrayPropertyInterface<Type>::PropertyType;
203 using IT = ArrayPropertyInterface<Type>;
204 using InterfaceType = BASE_NS::conditional_t<BASE_NS::is_const_v<Type>, const IT*, IT*>;
205
META_NO_COPY_MOVE(TypedArrayPropertyLock)206 META_NO_COPY_MOVE(TypedArrayPropertyLock)
207
208 public:
209 explicit TypedArrayPropertyLock(PropertyType p) : ArrayPropertyInterface<Type>(p)
210 {
211 if (auto i = interface_cast<ILockable>(p)) {
212 i->Lock();
213 }
214 }
~TypedArrayPropertyLock()215 ~TypedArrayPropertyLock()
216 {
217 if (auto i = interface_cast<ILockable>(this->GetProperty())) {
218 i->Unlock();
219 }
220 }
221
222 InterfaceType operator->() const
223 {
224 return const_cast<TypedArrayPropertyLock*>(this);
225 }
226 };
227
228 template<typename Property>
229 class ArrayPropertyLock final : public ArrayPropertyBaseType<Property> {
230 using InterfaceType = ArrayPropertyBaseType<Property>*;
231
META_NO_COPY_MOVE(ArrayPropertyLock)232 META_NO_COPY_MOVE(ArrayPropertyLock)
233
234 public:
235 explicit ArrayPropertyLock(BASE_NS::shared_ptr<Property> p) : ArrayPropertyBaseType<Property>(p.get())
236 {
237 if (auto i = interface_cast<ILockable>(p)) {
238 i->Lock();
239 }
240 }
~ArrayPropertyLock()241 ~ArrayPropertyLock()
242 {
243 if (auto i = interface_cast<ILockable>(this->GetProperty())) {
244 i->Unlock();
245 }
246 }
247
248 InterfaceType operator->() const
249 {
250 return const_cast<ArrayPropertyLock*>(this);
251 }
252 };
253
254 META_END_NAMESPACE()
255
256 #endif
257