• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/property.h>
20 
META_BEGIN_NAMESPACE()21 META_BEGIN_NAMESPACE()
22 
23 template<typename Base>
24 class ConstTypelessArrayPropertyInterfaceImpl : public Base {
25 public:
26     using IndexType = IArrayAny::IndexType;
27 
28     template<typename Prop>
29     explicit ConstTypelessArrayPropertyInterfaceImpl(Prop* p) : Base(p)
30     {}
31 
32     /// Get array size
33     IndexType GetSize() const
34     {
35         if (auto arr = interface_cast<IArrayAny>(&this->GetValueAny())) {
36             return arr->GetSize();
37         }
38         return {};
39     }
40     /**
41      * @brief Get value at given location to an any
42      * @param index Location in the array to get
43      * @param any Any where the value is copied to.
44      * @notice The any needs to be compatible with the array item type.
45      * @return Result of the operation
46      */
47     AnyReturnValue GetAnyAt(IndexType index, IAny& any) const
48     {
49         if (auto arr = interface_cast<IArrayAny>(&this->GetValueAny())) {
50             return arr->GetAnyAt(index, any);
51         }
52         return AnyReturn::INCOMPATIBLE_TYPE;
53     }
54     /**
55      * @brief Construct any and get value for given location
56      * @param index Location in the array to get
57      * @return Pointer to any with the value at location 'index' or nullptr in case of failure.
58      */
59     IAny::Ptr GetAnyAt(IndexType index) const
60     {
61         IAny::Ptr res = ConstructItemAny();
62         if (res) {
63             if (!GetAnyAt(index, *res)) {
64                 res.reset();
65             }
66         }
67         return res;
68     }
69     /// Construct any with the array item type
70     IAny::Ptr ConstructItemAny() const
71     {
72         IAny::Ptr res;
73         if (auto i = interface_cast<IPropertyInternalAny>(this->p_)) {
74             if (auto internal = i->GetInternalAny()) {
75                 res = internal->Clone({ CloneValueType::DEFAULT_VALUE, TypeIdRole::ITEM });
76             }
77         }
78         return res;
79     }
80 };
81 
82 using ConstTypelessArrayPropertyInterface = ConstTypelessArrayPropertyInterfaceImpl<ConstTypelessPropertyInterface>;
83 
84 class TypelessArrayPropertyInterface : public ConstTypelessArrayPropertyInterfaceImpl<TypelessPropertyInterface> {
85 public:
86     using PropertyType = IProperty*;
87     using IndexType = IArrayAny::IndexType;
88 
TypelessArrayPropertyInterface(PropertyType p)89     TypelessArrayPropertyInterface(PropertyType p)
90         : ConstTypelessArrayPropertyInterfaceImpl<TypelessPropertyInterface>(p)
91     {}
92 
93     /**
94      * @brief Set value for given location from an any
95      * @param index Location in the array to set
96      * @param any Any to copy value from.
97      * @return Result of the operation
98      */
SetAnyAt(IndexType index,const IAny & any)99     AnyReturnValue SetAnyAt(IndexType index, const IAny& any)
100     {
101         if (auto c = this->GetValueAny().Clone(true)) {
102             if (auto arr = interface_cast<IArrayAny>(c)) {
103                 auto res = arr->SetAnyAt(index, any);
104                 return res ? this->SetValueAny(*arr) : res;
105             }
106         }
107         return AnyReturn::INCOMPATIBLE_TYPE;
108     }
109     /**
110      * @brief Add value to end of array from an any
111      * @param any Any to copy value from.
112      * @return Result of the operation
113      */
AddAny(const IAny & any)114     AnyReturnValue AddAny(const IAny& any)
115     {
116         return InsertAnyAt(-1, any);
117     }
118     /**
119      * @brief Insert value to given location from an any
120      * @param index Location in the array to insert.
121      * @param any Any to copy value from.
122      * @return Result of the operation
123      */
InsertAnyAt(IndexType index,const IAny & v)124     AnyReturnValue InsertAnyAt(IndexType index, const IAny& v)
125     {
126         if (auto c = this->GetValueAny().Clone(true)) {
127             if (auto arr = interface_cast<IArrayAny>(c)) {
128                 auto res = arr->InsertAnyAt(index, v);
129                 return res ? this->SetValueAny(*arr) : res;
130             }
131         }
132         return AnyReturn::INCOMPATIBLE_TYPE;
133     }
134     /**
135      * @brief Remove value at give location
136      * @param index Location in the array to remove from.
137      * @return true on success
138      */
RemoveAt(IndexType index)139     bool RemoveAt(IndexType index)
140     {
141         if (auto c = this->GetValueAny().Clone(true)) {
142             if (auto arr = interface_cast<IArrayAny>(c)) {
143                 return arr->RemoveAt(index) && this->SetValueAny(*arr);
144             }
145         }
146         return false;
147     }
148 };
149 
150 template<typename Type>
151 using ArrayPropertyBaseType = BASE_NS::conditional_t<BASE_NS::is_const_v<Type>, ConstTypelessArrayPropertyInterface,
152     TypelessArrayPropertyInterface>;
153 
154 template<typename Type>
155 class ArrayPropertyInterface : public ArrayPropertyBaseType<Type> {
156     using Super = ArrayPropertyBaseType<Type>;
157 
158 public:
159     using ValueType = BASE_NS::remove_const_t<Type>;
160     using PropertyType = typename PropertyBaseType<Type>::PropertyType;
161     using IndexType = IArrayAny::IndexType;
162 
ArrayPropertyInterface(PropertyType p)163     explicit ArrayPropertyInterface(PropertyType p) : Super(p) {}
164 
165     /**
166      * @brief Get value at given location
167      * @param index Location from which to get value
168      * @return Value at given location or value-initialized value in case failure
169      */
GetValueAt(IndexType index)170     ValueType GetValueAt(IndexType index) const
171     {
172         Any<ValueType> any;
173         if (auto arr = interface_cast<IArrayAny>(&this->GetValueAny())) {
174             arr->GetAnyAt(index, any);
175         }
176         return any.InternalGetValue();
177     }
178     /**
179      * @brief Set value at given location
180      * @param index Location to set value
181      * @param v Value to set
182      * @return True on success
183      */
SetValueAt(IndexType index,const Type & v)184     bool SetValueAt(IndexType index, const Type& v)
185     {
186         return this->SetAnyAt(index, Any<ValueType> { v });
187     }
188     /**
189      * @brief Ad value at the end of array
190      * @param v Value to add
191      * @return True on success
192      */
AddValue(const Type & v)193     bool AddValue(const Type& v)
194     {
195         return InsertValueAt(-1, v);
196     }
197     /**
198      * @brief Insert value at given location
199      * @param index Location to insert value
200      * @param v Value to insert
201      * @return True on success
202      */
InsertValueAt(IndexType index,const Type & v)203     bool InsertValueAt(IndexType index, const Type& v)
204     {
205         return this->InsertAnyAt(index, Any<ValueType> { v });
206     }
207     /// Get default value of the array property
GetDefaultValue()208     BASE_NS::vector<ValueType> GetDefaultValue() const
209     {
210         BASE_NS::vector<ValueType> v;
211         this->GetDefaultValueAny().GetValue(v);
212         return v;
213     }
214     /// Set default value of the array property
SetDefaultValue(BASE_NS::array_view<const ValueType> value)215     AnyReturnValue SetDefaultValue(BASE_NS::array_view<const ValueType> value)
216     {
217         return this->SetDefaultValueAny(ArrayAny<ValueType>(value));
218     }
219 
220     /// Set default value of the array property
221     template<typename T, typename = BASE_NS::enable_if_t<BASE_NS::is_same_v<T, ValueType>>>
SetDefaultValue(BASE_NS::vector<T> value)222     AnyReturnValue SetDefaultValue(BASE_NS::vector<T> value)
223     {
224         return this->SetDefaultValueAny(ArrayAny<ValueType>(BASE_NS::move(value)));
225     }
226 
227     /// Set default value of the array property and optionally reset current value to it
SetDefaultValue(BASE_NS::vector<ValueType> value,bool resetToDefault)228     AnyReturnValue SetDefaultValue(BASE_NS::vector<ValueType> value, bool resetToDefault)
229     {
230         auto ret = this->SetDefaultValueAny(ArrayAny<ValueType>(BASE_NS::move(value)));
231         if (resetToDefault && ret) {
232             this->ResetValue();
233         }
234         return ret;
235     }
236     /// Get value of the array property
GetValue()237     BASE_NS::vector<ValueType> GetValue() const
238     {
239         BASE_NS::vector<ValueType> v {};
240         this->GetValueAny().GetValue(v);
241         return v;
242     }
243     /// Set value of the array property
SetValue(BASE_NS::array_view<const ValueType> value)244     AnyReturnValue SetValue(BASE_NS::array_view<const ValueType> value)
245     {
246         return this->SetValueAny(ArrayAny<ValueType>(value));
247     }
248     /// Set value of the array property
249     template<typename T, typename = BASE_NS::enable_if_t<BASE_NS::is_same_v<T, ValueType>>>
SetValue(BASE_NS::vector<T> value)250     AnyReturnValue SetValue(BASE_NS::vector<T> value)
251     {
252         return this->SetValueAny(ArrayAny<ValueType>(BASE_NS::move(value)));
253     }
254     /// Find index of first matching value in the array property or -1 if no such value
FindFirstValueOf(const Type & v)255     IndexType FindFirstValueOf(const Type& v) const
256     {
257         for (IndexType i = 0; i != this->GetSize(); ++i) {
258             if (GetValueAt(i) == v) {
259                 return i;
260             }
261         }
262         return -1;
263     }
264 };
265 
266 template<typename Type>
267 class TypedArrayPropertyLock final : public ArrayPropertyInterface<Type> {
268     using PropertyType = typename ArrayPropertyInterface<Type>::PropertyType;
269     using IT = ArrayPropertyInterface<Type>;
270     using InterfaceType = BASE_NS::conditional_t<BASE_NS::is_const_v<Type>, const IT*, IT*>;
271 
META_NO_COPY_MOVE(TypedArrayPropertyLock)272     META_NO_COPY_MOVE(TypedArrayPropertyLock)
273 
274     bool CanConstructFrom(PropertyType p) const
275     {
276         return p && p->IsCompatible(META_NS::GetArrayTypeId<BASE_NS::remove_const_t<Type>>());
277     }
278 
279 public:
TypedArrayPropertyLock(NoCheckT,PropertyType p)280     TypedArrayPropertyLock(NoCheckT, PropertyType p) : ArrayPropertyInterface<Type>(p)
281     {
282         if (auto i = interface_cast<ILockable>(this->GetProperty())) {
283             i->Lock();
284         }
285     }
TypedArrayPropertyLock(PropertyType p)286     explicit TypedArrayPropertyLock(PropertyType p) : TypedArrayPropertyLock(NOCHECK, CanConstructFrom(p) ? p : nullptr)
287     {}
TypedArrayPropertyLock(const IProperty::Ptr & p)288     explicit TypedArrayPropertyLock(const IProperty::Ptr& p) : TypedArrayPropertyLock(p.get()) {}
TypedArrayPropertyLock(const IProperty::ConstPtr & p)289     explicit TypedArrayPropertyLock(const IProperty::ConstPtr& p) : TypedArrayPropertyLock(p.get()) {}
~TypedArrayPropertyLock()290     ~TypedArrayPropertyLock()
291     {
292         if (auto i = interface_cast<ILockable>(this->GetProperty())) {
293             i->Unlock();
294         }
295     }
296 
297     InterfaceType operator->() const
298     {
299         return const_cast<TypedArrayPropertyLock*>(this);
300     }
301 
IsValid()302     bool IsValid() const
303     {
304         return this->GetProperty() != nullptr;
305     }
306 
307     explicit operator bool() const
308     {
309         return IsValid();
310     }
311 };
312 
313 template<typename Property>
314 class ArrayPropertyLock final : public ArrayPropertyBaseType<Property> {
315     using InterfaceType = ArrayPropertyBaseType<Property>*;
316 
META_NO_COPY_MOVE(ArrayPropertyLock)317     META_NO_COPY_MOVE(ArrayPropertyLock)
318 
319     bool CanConstructFrom(Property* p) const
320     {
321         auto i = interface_cast<IPropertyInternalAny>(p);
322         return i && IsArray(i->GetInternalAny());
323     }
324 
325 public:
ArrayPropertyLock(NoCheckT,Property * p)326     ArrayPropertyLock(NoCheckT, Property* p) : ArrayPropertyBaseType<Property>(p)
327     {
328         if (auto i = interface_cast<ILockable>(this->GetProperty())) {
329             i->Lock();
330         }
331     }
332 
ArrayPropertyLock(Property * p)333     explicit ArrayPropertyLock(Property* p) : ArrayPropertyLock(NOCHECK, CanConstructFrom(p) ? p : nullptr) {}
334 
ArrayPropertyLock(BASE_NS::shared_ptr<Property> p)335     explicit ArrayPropertyLock(BASE_NS::shared_ptr<Property> p) : ArrayPropertyLock(p.get()) {}
~ArrayPropertyLock()336     ~ArrayPropertyLock()
337     {
338         if (auto i = interface_cast<ILockable>(this->GetProperty())) {
339             i->Unlock();
340         }
341     }
342 
343     InterfaceType operator->() const
344     {
345         return const_cast<ArrayPropertyLock*>(this);
346     }
347 
IsValid()348     bool IsValid() const
349     {
350         return this->GetProperty() != nullptr;
351     }
352 
353     explicit operator bool() const
354     {
355         return IsValid();
356     }
357 };
358 
359 META_END_NAMESPACE()
360 
361 #endif
362