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_API_UTIL_H
17 #define META_API_UTIL_H
18
19 #include <meta/api/locking.h>
20 #include <meta/base/ids.h>
21 #include <meta/interface/animation/intf_interpolator.h>
22 #include <meta/interface/intf_any.h>
23 #include <meta/interface/intf_object_registry.h>
24 #include <meta/interface/intf_value.h>
25 #include <meta/interface/property/array_property.h>
26 #include <meta/interface/property/intf_modifier.h>
27 #include <meta/interface/property/property.h>
28
META_BEGIN_NAMESPACE()29 META_BEGIN_NAMESPACE()
30
31 /// Get shared_ptr of IInterface from an any, or nullptr if not compatible
32 inline BASE_NS::shared_ptr<CORE_NS::IInterface> GetPointer(const IAny& any)
33 {
34 BASE_NS::shared_ptr<CORE_NS::IInterface> ret;
35 any.GetValue(ret);
36 return ret;
37 }
38
39 /// Get shared_ptr of IInterface from an any ptr, or nullptr if not compatible
GetPointer(const IAny::Ptr & any)40 inline BASE_NS::shared_ptr<CORE_NS::IInterface> GetPointer(const IAny::Ptr& any)
41 {
42 return any ? GetPointer(*any) : nullptr;
43 }
44
45 /// Get shared_ptr of IInterface from an any, or nullptr if not compatible
GetConstPointer(const IAny & any)46 inline BASE_NS::shared_ptr<const CORE_NS::IInterface> GetConstPointer(const IAny& any)
47 {
48 BASE_NS::shared_ptr<const CORE_NS::IInterface> ret;
49 any.GetValue(ret);
50 return ret;
51 }
52
53 /// Get shared_ptr of IInterface from an any, or nullptr if not compatible
GetConstPointer(const IAny::ConstPtr & any)54 inline BASE_NS::shared_ptr<const CORE_NS::IInterface> GetConstPointer(const IAny::ConstPtr& any)
55 {
56 return any ? GetConstPointer(*any) : nullptr;
57 }
58
59 /// Get shared_ptr of IInterface from an any ptr, or nullptr if not compatible
GetPointer(const IAny::ConstPtr & any)60 inline BASE_NS::shared_ptr<const CORE_NS::IInterface> GetPointer(const IAny::ConstPtr& any)
61 {
62 return any ? GetConstPointer(*any) : nullptr;
63 }
64
65 /// Get interface pointer from an any, or nullptr if not compatible
66 template<typename Interface>
GetPointer(const IAny & any)67 inline BASE_NS::shared_ptr<Interface> GetPointer(const IAny& any)
68 {
69 return interface_pointer_cast<Interface>(GetPointer(any));
70 }
71
72 /// Returns IIinterface pointer if property contains a pointer that can be converted to it.
GetPointer(const IProperty::ConstPtr & p)73 inline BASE_NS::shared_ptr<CORE_NS::IInterface> GetPointer(const IProperty::ConstPtr& p)
74 {
75 InterfaceSharedLock lock { p };
76 return lock ? GetPointer(p->GetValue()) : nullptr;
77 }
78
79 /// Returns IIinterface pointer if property contains a pointer that can be converted to it.
GetConstPointer(const IProperty::ConstPtr & p)80 inline BASE_NS::shared_ptr<const CORE_NS::IInterface> GetConstPointer(const IProperty::ConstPtr& p)
81 {
82 InterfaceSharedLock lock { p };
83 return lock ? GetConstPointer(p->GetValue()) : nullptr;
84 }
85
86 /// Returns interface pointer if property contains a pointer that can be converted to it.
87 template<typename Interface>
GetPointer(const IProperty::ConstPtr & p)88 inline BASE_NS::shared_ptr<Interface> GetPointer(const IProperty::ConstPtr& p)
89 {
90 return interface_pointer_cast<Interface>(GetPointer(p));
91 }
92
93 /// Returns interface pointer if property contains a pointer that can be converted to it.
94 template<typename Interface>
GetConstPointer(const IProperty::ConstPtr & p)95 inline BASE_NS::shared_ptr<const Interface> GetConstPointer(const IProperty::ConstPtr& p)
96 {
97 return interface_pointer_cast<Interface>(GetConstPointer(p));
98 }
99
100 /// Returns the internal any from property
GetInternalAny(const IProperty::ConstPtr & p)101 inline IAny::ConstPtr GetInternalAny(const IProperty::ConstPtr& p)
102 {
103 auto i = interface_cast<IPropertyInternalAny>(p);
104 return i ? i->GetInternalAny() : nullptr;
105 }
106
107 /// Returns the internal any from property
GetInternalAny(const IProperty & p)108 inline IAny::ConstPtr GetInternalAny(const IProperty& p)
109 {
110 auto i = interface_cast<IPropertyInternalAny>(&p);
111 return i ? i->GetInternalAny() : nullptr;
112 }
113
114 /// Set IIinterface pointer for any if it is compatible
SetPointer(IAny & any,const BASE_NS::shared_ptr<CORE_NS::IInterface> & p)115 inline bool SetPointer(IAny& any, const BASE_NS::shared_ptr<CORE_NS::IInterface>& p)
116 {
117 return any.SetValue(p);
118 }
119
120 /// Set IIinterface pointer for any if it is compatible
SetPointer(IAny & any,const BASE_NS::shared_ptr<const CORE_NS::IInterface> & p)121 inline bool SetPointer(IAny& any, const BASE_NS::shared_ptr<const CORE_NS::IInterface>& p)
122 {
123 return any.SetValue(p);
124 }
125
126 /// Set IIinterface pointer for property if it is compatible
SetPointer(const IProperty::Ptr & p,const BASE_NS::shared_ptr<CORE_NS::IInterface> & ptr)127 inline bool SetPointer(const IProperty::Ptr& p, const BASE_NS::shared_ptr<CORE_NS::IInterface>& ptr)
128 {
129 if (InterfaceSharedLock lock { p }) {
130 if (auto inany = GetInternalAny(p)) {
131 if (auto any = inany->Clone(false)) {
132 if (any->SetValue(ptr)) {
133 return p->SetValue(*any);
134 }
135 }
136 }
137 }
138 return false;
139 }
140
141 /// Set IIinterface pointer for property if it is compatible
SetPointer(const IProperty::Ptr & p,const BASE_NS::shared_ptr<const CORE_NS::IInterface> & ptr)142 inline bool SetPointer(const IProperty::Ptr& p, const BASE_NS::shared_ptr<const CORE_NS::IInterface>& ptr)
143 {
144 if (InterfaceSharedLock lock { p }) {
145 if (auto inany = GetInternalAny(p)) {
146 if (auto any = inany->Clone(false)) {
147 if (any->SetValue(ptr)) {
148 return p->SetValue(*any);
149 }
150 }
151 }
152 }
153 return false;
154 }
155
156 /// Set IIinterface pointer for property if it is compatible
157 template<typename Interface>
SetPointer(const IProperty::Ptr & p,const BASE_NS::shared_ptr<Interface> & ptr)158 inline bool SetPointer(const IProperty::Ptr& p, const BASE_NS::shared_ptr<Interface>& ptr)
159 {
160 return SetPointer(p, interface_pointer_cast<CORE_NS::IInterface>(ptr));
161 }
162
163 /**
164 * @brief Duplicate property type without values or modifiers
165 * @param obr Object registry to use
166 * @param p Property to duplicate
167 * @param name Name for the new property, name of p is used if empty
168 * @return New property with same type as p
169 */
170 inline IProperty::Ptr DuplicatePropertyType(IObjectRegistry& obr, IProperty::ConstPtr p, BASE_NS::string_view name = {})
171 {
172 IProperty::Ptr dup;
173 PropertyLock lock { p };
174 if (auto obj = interface_cast<IObject>(p)) {
175 dup = obr.GetPropertyRegister().Create(obj->GetClassId(), name.empty() ? p->GetName() : name);
176 if (auto dupi = interface_cast<IPropertyInternalAny>(dup)) {
177 if (auto any = GetInternalAny(p)) {
178 dupi->SetInternalAny(any->Clone(false));
179 }
180 }
181 }
182 return dup;
183 }
184
185 /// Get value of property or given default value if property not set or incompatible
186 template<typename Type>
187 Type GetValue(const Property<Type>& p, NonDeduced_t<BASE_NS::remove_const_t<Type>> defaultValue = {}) noexcept
188 {
189 return p ? p->GetValue() : BASE_NS::move(defaultValue);
190 }
191 /// Get value of property or given default value if property not set or incompatible
192 template<typename Type>
193 Type GetValue(const IProperty::ConstPtr& p, NonDeduced_t<BASE_NS::remove_const_t<Type>> defaultValue = {}) noexcept
194 {
195 return GetValue(Property<Type>(p), BASE_NS::move(defaultValue));
196 }
197 /// Get value of property or given default value if property not set or incompatible
198 template<typename Type>
199 Type GetValue(const IProperty::ConstWeakPtr& p, NonDeduced_t<BASE_NS::remove_const_t<Type>> defaultValue = {}) noexcept
200 {
201 return GetValue<Type>(p.lock(), BASE_NS::move(defaultValue));
202 }
203 // to disambiguate
204 /// Get value of property or given default value if property not set or incompatible
205 template<typename Type>
206 Type GetValue(const IProperty::Ptr& p, NonDeduced_t<BASE_NS::remove_const_t<Type>> defaultValue = {}) noexcept
207 {
208 return GetValue(Property<Type>(p), BASE_NS::move(defaultValue));
209 }
210 // to disambiguate
211 /// Get value of property or given default value if property not set or incompatible
212 template<typename Type>
213 Type GetValue(const IProperty::WeakPtr& p, NonDeduced_t<BASE_NS::remove_const_t<Type>> defaultValue = {}) noexcept
214 {
215 return GetValue<Type>(p.lock(), BASE_NS::move(defaultValue));
216 }
217 /// Set value for property, true on success
218 template<typename Type>
SetValue(Property<Type> property,const NonDeduced_t<Type> & value)219 bool SetValue(Property<Type> property, const NonDeduced_t<Type>& value) noexcept
220 {
221 return property && property->SetValue(value);
222 }
223 /// Set value for property, true on success
224 template<typename Type>
SetValue(IProperty::Ptr p,const NonDeduced_t<Type> & value)225 bool SetValue(IProperty::Ptr p, const NonDeduced_t<Type>& value) noexcept
226 {
227 return SetValue(Property<Type>(p), value);
228 }
229 /// Set value for property, true on success
230 template<typename Type>
SetValue(IProperty::WeakPtr p,const NonDeduced_t<Type> & value)231 bool SetValue(IProperty::WeakPtr p, const NonDeduced_t<Type>& value) noexcept
232 {
233 return SetValue<Type>(p.lock(), value);
234 }
235 /// Copy value from src to dst property
Copy(const IProperty::ConstPtr & src,const IProperty::Ptr & dst)236 inline bool Copy(const IProperty::ConstPtr& src, const IProperty::Ptr& dst)
237 {
238 PropertyLock source(src);
239 PropertyLock dest(dst);
240 return dest->SetValueAny(source->GetValueAny());
241 }
242 /// Check if property is compatible with given type id and direction
243 inline bool IsCompatible(
244 const IProperty& prop, const TypeId& id, CompatibilityDirection dir = CompatibilityDirection::BOTH)
245 {
246 bool res = false;
247 if (auto iany = GetInternalAny(prop)) {
248 res = IsCompatible(*iany, id, dir);
249 }
250 return res;
251 }
252 /// Check if property is compatible with given type id and direction
253 inline bool IsCompatible(
254 const IProperty::ConstPtr& prop, const TypeId& id, CompatibilityDirection dir = CompatibilityDirection::BOTH)
255 {
256 return prop && IsCompatible(*prop, id, dir);
257 }
258 /// Check if property is compatible with type and direction
259 template<typename T>
260 inline bool IsCompatibleWith(const IProperty::ConstPtr& prop, CompatibilityDirection dir = CompatibilityDirection::BOTH)
261 {
262 return IsCompatible(prop, GetTypeId<BASE_NS::remove_const_t<BASE_NS::remove_reference_t<T>>>(), dir);
263 }
264 /// Check if property is compatible to set value with given type id
IsSetCompatible(const IProperty::ConstPtr & prop,const TypeId & id)265 inline bool IsSetCompatible(const IProperty::ConstPtr& prop, const TypeId& id)
266 {
267 return IsCompatible(prop, id, CompatibilityDirection::SET);
268 }
269 /// Check if property is compatible to get value with given type id
IsGetCompatible(const IProperty::ConstPtr & prop,const TypeId & id)270 inline bool IsGetCompatible(const IProperty::ConstPtr& prop, const TypeId& id)
271 {
272 return IsCompatible(prop, id, CompatibilityDirection::GET);
273 }
274 /// Check if property is compatible to set value with type
275 template<typename T>
IsSetCompatibleWith(const IProperty::ConstPtr & prop)276 inline bool IsSetCompatibleWith(const IProperty::ConstPtr& prop)
277 {
278 return IsCompatibleWith<T>(prop, CompatibilityDirection::SET);
279 }
280 /// Check if property is compatible to get value with type
281 template<typename T>
IsGetCompatibleWith(const IProperty::ConstPtr & prop)282 inline bool IsGetCompatibleWith(const IProperty::ConstPtr& prop)
283 {
284 return IsCompatibleWith<T>(prop, CompatibilityDirection::GET);
285 }
286 /**
287 * @brief Typeless interpolate between two anys using property as result
288 * @param inter Interpolator to use
289 * @param output PRoperty to use as result
290 * @param from Start of the range
291 * @param to End of the range
292 * @param t The interpolation position in range [0,1]
293 */
Interpolate(IInterpolator::ConstPtr inter,const IProperty::Ptr & output,const IAny::ConstPtr & from,const IAny::ConstPtr & to,float t)294 inline AnyReturnValue Interpolate(IInterpolator::ConstPtr inter, const IProperty::Ptr& output,
295 const IAny::ConstPtr& from, const IAny::ConstPtr& to, float t)
296 {
297 if (from && to) {
298 if (auto i = interface_cast<IPropertyInternalAny>(output)) {
299 PropertyLock lock { output };
300 if (auto iany = i->GetInternalAny()) {
301 auto ret = inter->Interpolate(*iany, *from, *to, t);
302 lock.SetValueAny(*iany);
303 return ret;
304 }
305 }
306 }
307 return AnyReturn::FAIL;
308 }
309 /// Check if any is get-compatible with the given IValue
IsValueGetCompatible(const IAny & any,const IValue & value)310 inline bool IsValueGetCompatible(const IAny& any, const IValue& value)
311 {
312 for (auto&& t : any.GetCompatibleTypes(CompatibilityDirection::GET)) {
313 if (value.IsCompatible(t)) {
314 return true;
315 }
316 }
317 return false;
318 }
319 /// Check if any is get-compatible with the given IModifier
IsModifierGetCompatible(const IAny & any,const IModifier & value)320 inline bool IsModifierGetCompatible(const IAny& any, const IModifier& value)
321 {
322 for (auto&& t : any.GetCompatibleTypes(CompatibilityDirection::GET)) {
323 if (value.IsCompatible(t)) {
324 return true;
325 }
326 }
327 return false;
328 }
329 /// Returns the top most value interface from property that implements Interface or nullptr if no such
330 template<typename Interface>
GetFirstValueFromProperty(const IProperty::ConstPtr & p)331 typename Interface::Ptr GetFirstValueFromProperty(const IProperty::ConstPtr& p)
332 {
333 if (auto i = interface_cast<IStackProperty>(p)) {
334 PropertyLock lock { p };
335 TypeId ids[] = { Interface::UID };
336 auto values = i->GetValues(ids, false);
337 if (!values.empty()) {
338 return interface_pointer_cast<Interface>(values.back());
339 }
340 }
341 return nullptr;
342 }
343
344 /// Check if property contains pointer that can be extracted as constant IInterface
IsGetPointer(const IProperty::ConstPtr & p)345 inline bool IsGetPointer(const IProperty::ConstPtr& p)
346 {
347 return IsGetCompatibleWith<SharedPtrConstIInterface>(p);
348 }
349
350 /// Check if property contains pointer that can be set as IInterface
IsSetPointer(const IProperty::ConstPtr & p)351 inline bool IsSetPointer(const IProperty::ConstPtr& p)
352 {
353 return IsSetCompatibleWith<SharedPtrIInterface>(p);
354 }
355
356 META_END_NAMESPACE()
357
358 #endif
359