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 IAny::Ptr GetAnyAt(IndexType index) const
48 {
49 IAny::Ptr res = ConstructItemAny();
50 if (res) {
51 if (!GetAnyAt(index, *res)) {
52 res.reset();
53 }
54 }
55 return res;
56 }
57 IAny::Ptr ConstructItemAny() const
58 {
59 IAny::Ptr res;
60 if (auto i = interface_cast<IPropertyInternalAny>(this->p_)) {
61 if (auto internal = i->GetInternalAny()) {
62 res = internal->Clone({ CloneValueType::DEFAULT_VALUE, TypeIdRole::ITEM });
63 }
64 }
65 return res;
66 }
67 };
68
69 using ConstTypelessArrayPropertyInterface = ConstTypelessArrayPropertyInterfaceImpl<ConstTypelessPropertyInterface>;
70
71 class TypelessArrayPropertyInterface : public ConstTypelessArrayPropertyInterfaceImpl<TypelessPropertyInterface> {
72 public:
73 using PropertyType = IProperty*;
74 using IndexType = IArrayAny::IndexType;
75
TypelessArrayPropertyInterface(PropertyType p)76 TypelessArrayPropertyInterface(PropertyType p)
77 : ConstTypelessArrayPropertyInterfaceImpl<TypelessPropertyInterface>(p)
78 {}
79
SetAnyAt(IndexType index,const IAny & any)80 AnyReturnValue SetAnyAt(IndexType index, const IAny& any)
81 {
82 if (auto c = this->GetValueAny().Clone(true)) {
83 if (auto arr = interface_cast<IArrayAny>(c)) {
84 auto res = arr->SetAnyAt(index, any);
85 return res ? this->SetValueAny(*arr) : res;
86 }
87 }
88 return AnyReturn::INCOMPATIBLE_TYPE;
89 }
AddAny(const IAny & any)90 AnyReturnValue AddAny(const IAny& any)
91 {
92 return InsertAnyAt(-1, any);
93 }
InsertAnyAt(IndexType index,const IAny & v)94 AnyReturnValue InsertAnyAt(IndexType index, const IAny& v)
95 {
96 if (auto c = this->GetValueAny().Clone(true)) {
97 if (auto arr = interface_cast<IArrayAny>(c)) {
98 auto res = arr->InsertAnyAt(index, v);
99 return res ? this->SetValueAny(*arr) : res;
100 }
101 }
102 return AnyReturn::INCOMPATIBLE_TYPE;
103 }
RemoveAt(IndexType index)104 bool RemoveAt(IndexType index)
105 {
106 if (auto c = this->GetValueAny().Clone(true)) {
107 if (auto arr = interface_cast<IArrayAny>(c)) {
108 return arr->RemoveAt(index) && this->SetValueAny(*arr);
109 }
110 }
111 return false;
112 }
113 };
114
115 template<typename Type>
116 using ArrayPropertyBaseType = BASE_NS::conditional_t<BASE_NS::is_const_v<Type>, ConstTypelessArrayPropertyInterface,
117 TypelessArrayPropertyInterface>;
118
119 template<typename Type>
120 class ArrayPropertyInterface : public ArrayPropertyBaseType<Type> {
121 using Super = ArrayPropertyBaseType<Type>;
122
123 public:
124 using ValueType = BASE_NS::remove_const_t<Type>;
125 using PropertyType = typename PropertyBaseType<Type>::PropertyType;
126 using IndexType = IArrayAny::IndexType;
127
ArrayPropertyInterface(PropertyType p)128 explicit ArrayPropertyInterface(PropertyType p) : Super(p) {}
129
GetValueAt(IndexType index)130 ValueType GetValueAt(IndexType index) const
131 {
132 Any<ValueType> any;
133 if (auto arr = interface_cast<IArrayAny>(&this->GetValueAny())) {
134 arr->GetAnyAt(index, any);
135 }
136 return any.InternalGetValue();
137 }
SetValueAt(IndexType index,const Type & v)138 bool SetValueAt(IndexType index, const Type& v)
139 {
140 return this->SetAnyAt(index, Any<ValueType> { v });
141 }
AddValue(const Type & v)142 bool AddValue(const Type& v)
143 {
144 return InsertValueAt(-1, v);
145 }
InsertValueAt(IndexType index,const Type & v)146 bool InsertValueAt(IndexType index, const Type& v)
147 {
148 return this->InsertAnyAt(index, Any<ValueType> { v });
149 }
GetDefaultValue()150 BASE_NS::vector<ValueType> GetDefaultValue() const
151 {
152 BASE_NS::vector<ValueType> v;
153 this->GetDefaultValueAny().GetValue(v);
154 return v;
155 }
156
SetDefaultValue(BASE_NS::array_view<const ValueType> value)157 AnyReturnValue SetDefaultValue(BASE_NS::array_view<const ValueType> value)
158 {
159 return this->SetDefaultValueAny(ArrayAny<ValueType>(value));
160 }
161
162 template<typename T, typename = BASE_NS::enable_if_t<BASE_NS::is_same_v<T, ValueType>>>
SetDefaultValue(BASE_NS::vector<T> value)163 AnyReturnValue SetDefaultValue(BASE_NS::vector<T> value)
164 {
165 return this->SetDefaultValueAny(ArrayAny<ValueType>(BASE_NS::move(value)));
166 }
167
SetDefaultValue(BASE_NS::vector<ValueType> value,bool resetToDefault)168 AnyReturnValue SetDefaultValue(BASE_NS::vector<ValueType> value, bool resetToDefault)
169 {
170 auto ret = this->SetDefaultValueAny(ArrayAny<ValueType>(BASE_NS::move(value)));
171 if (resetToDefault && ret) {
172 this->ResetValue();
173 }
174 return ret;
175 }
176
GetValue()177 BASE_NS::vector<ValueType> GetValue() const
178 {
179 BASE_NS::vector<ValueType> v {};
180 this->GetValueAny().GetValue(v);
181 return v;
182 }
183
SetValue(BASE_NS::array_view<const ValueType> value)184 AnyReturnValue SetValue(BASE_NS::array_view<const ValueType> value)
185 {
186 return this->SetValueAny(ArrayAny<ValueType>(value));
187 }
188
189 template<typename T, typename = BASE_NS::enable_if_t<BASE_NS::is_same_v<T, ValueType>>>
SetValue(BASE_NS::vector<T> value)190 AnyReturnValue SetValue(BASE_NS::vector<T> value)
191 {
192 return this->SetValueAny(ArrayAny<ValueType>(BASE_NS::move(value)));
193 }
194
FindFirstValueOf(const Type & v)195 IndexType FindFirstValueOf(const Type& v) const
196 {
197 for (IndexType i = 0; i != this->GetSize(); ++i) {
198 if (GetValueAt(i) == v) {
199 return i;
200 }
201 }
202 return -1;
203 }
204 };
205
206 template<typename Type>
207 class TypedArrayPropertyLock final : public ArrayPropertyInterface<Type> {
208 using PropertyType = typename ArrayPropertyInterface<Type>::PropertyType;
209 using IT = ArrayPropertyInterface<Type>;
210 using InterfaceType = BASE_NS::conditional_t<BASE_NS::is_const_v<Type>, const IT*, IT*>;
211
META_NO_COPY_MOVE(TypedArrayPropertyLock)212 META_NO_COPY_MOVE(TypedArrayPropertyLock)
213
214 bool CanConstructFrom(PropertyType p) const
215 {
216 return p && p->IsCompatible(META_NS::GetArrayTypeId<BASE_NS::remove_const_t<Type>>());
217 }
218 public:
TypedArrayPropertyLock(NoCheckT,PropertyType p)219 TypedArrayPropertyLock(NoCheckT, PropertyType p) : ArrayPropertyInterface<Type>(p)
220 {
221 if (auto i = interface_cast<ILockable>(this->GetProperty())) {
222 i->Lock();
223 }
224 }
TypedArrayPropertyLock(PropertyType p)225 explicit TypedArrayPropertyLock(PropertyType p) : TypedArrayPropertyLock(NOCHECK, CanConstructFrom(p) ? p : nullptr)
226 {}
TypedArrayPropertyLock(const IProperty::Ptr & p)227 explicit TypedArrayPropertyLock(const IProperty::Ptr& p) : TypedArrayPropertyLock(p.get()) {}
TypedArrayPropertyLock(const IProperty::ConstPtr & p)228 explicit TypedArrayPropertyLock(const IProperty::ConstPtr& p) : TypedArrayPropertyLock(p.get()) {}
~TypedArrayPropertyLock()229 ~TypedArrayPropertyLock()
230 {
231 if (auto i = interface_cast<ILockable>(this->GetProperty())) {
232 i->Unlock();
233 }
234 }
235
236 InterfaceType operator->() const
237 {
238 return const_cast<TypedArrayPropertyLock*>(this);
239 }
IsValid()240 bool IsValid() const
241 {
242 return this->GetProperty() != nullptr;
243 }
244 explicit operator bool() const
245 {
246 return IsValid();
247 }
248 };
249
250 template<typename Property>
251 class ArrayPropertyLock final : public ArrayPropertyBaseType<Property> {
252 using InterfaceType = ArrayPropertyBaseType<Property>*;
253
META_NO_COPY_MOVE(ArrayPropertyLock)254 META_NO_COPY_MOVE(ArrayPropertyLock)
255
256 bool CanConstructFrom(Property* p) const
257 {
258 auto i = interface_cast<IPropertyInternalAny>(p);
259 return i && IsArray(i->GetInternalAny());
260 }
261 public:
ArrayPropertyLock(NoCheckT,Property * p)262 ArrayPropertyLock(NoCheckT, Property* p) : ArrayPropertyBaseType<Property>(p)
263 {
264 if (auto i = interface_cast<ILockable>(this->GetProperty())) {
265 i->Lock();
266 }
267 }
ArrayPropertyLock(Property * p)268 explicit ArrayPropertyLock(Property* p) : ArrayPropertyLock(NOCHECK, CanConstructFrom(p) ? p : nullptr) {}
ArrayPropertyLock(BASE_NS::shared_ptr<Property> p)269 explicit ArrayPropertyLock(BASE_NS::shared_ptr<Property> p) : ArrayPropertyLock(p.get()) {}
~ArrayPropertyLock()270 ~ArrayPropertyLock()
271 {
272 if (auto i = interface_cast<ILockable>(this->GetProperty())) {
273 i->Unlock();
274 }
275 }
276
277 InterfaceType operator->() const
278 {
279 return const_cast<ArrayPropertyLock*>(this);
280 }
IsValid()281 bool IsValid() const
282 {
283 return this->GetProperty() != nullptr;
284 }
285 explicit operator bool() const
286 {
287 return IsValid();
288 }
289 };
290
291 META_END_NAMESPACE()
292
293 #endif
294