• 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_API_INTERFACE_OBJECT_H
17 #define META_API_INTERFACE_OBJECT_H
18 
19 #include <base/containers/shared_ptr.h>
20 #include <core/plugin/intf_interface.h>
21 
22 #include <meta/base/interface_macros.h>
23 #include <meta/base/interface_traits.h>
24 #include <meta/base/namespace.h>
25 
META_BEGIN_NAMESPACE()26 META_BEGIN_NAMESPACE()
27 
28 /**
29  * @brief Common base class for all InterfaceObjects.
30  */
31 class InterfaceObjectBase {
32 public:
33     InterfaceObjectBase() = default;
34     virtual ~InterfaceObjectBase() = default;
35     META_DEFAULT_COPY_MOVE(InterfaceObjectBase)
36     /// Returns true if InterfaceObject contains a valid shared_ptr<T>, false otherwise.
37     explicit operator bool() const noexcept
38     {
39         return GetInterfacePtr() != nullptr;
40     }
41     /// Returns true if underlying pointers are the same, false otherwise.
42     bool operator==(const InterfaceObjectBase& other) const noexcept
43     {
44         return GetInterfacePtr() == other.GetInterfacePtr();
45     }
46     /// Returns true if underlying pointers are different, false otherwise.
47     bool operator!=(const InterfaceObjectBase& other) const noexcept
48     {
49         return GetInterfacePtr() != other.GetInterfacePtr();
50     }
51     /// @see CORE_NS::IInterface::GetInterface
52     const CORE_NS::IInterface* GetInterface(const BASE_NS::Uid& uid) const
53     {
54         const auto p = GetInterfacePtr();
55         return p ? p->GetInterface(uid) : nullptr;
56     }
57     /// @see CORE_NS::IInterface::GetInterface
58     CORE_NS::IInterface* GetInterface(const BASE_NS::Uid& uid)
59     {
60         const auto p = GetInterfacePtr();
61         return p ? p->GetInterface(uid) : nullptr;
62     }
63 
64 protected:
65     virtual CORE_NS::IInterface* GetInterfacePtr() const noexcept = 0;
66 };
67 
68 namespace Internal {
69 /**
70  * @brief Converts vector types
71  * @param from The vector to convert from
72  * @return Returns a vector of InterfaceObjects initialized with elements from source array.
73  */
74 template<class To, class From>
ArrayCast(BASE_NS::vector<From> && from)75 constexpr auto ArrayCast(BASE_NS::vector<From>&& from) noexcept
76 {
77     if constexpr (BASE_NS::is_same_v<To, From>) {
78         return BASE_NS::move(from);
79     } else {
80         BASE_NS::vector<To> converted;
81         if (!from.empty()) {
82             converted.reserve(from.size());
83             for (auto&& n : from) {
84                 converted.emplace_back(n);
85             }
86         }
87         return converted;
88     }
89 }
90 
91 } // namespace Internal
92 
93 /**
94  * @brief The InterfaceObject class is the base BASE_NS::shared_ptr<T> wrapper inherited by actual interface wrapper
95  * objects.
96  */
97 template<typename T>
98 class InterfaceObject : public InterfaceObjectBase {
99     static_assert(
100         BASE_NS::is_base_of<CORE_NS::IInterface, T>(), "InterfaceObject type must be derived from CORE_NS::IInterface");
101 
102 public:
103     using UnderlyingType = T;
104     using Ptr = BASE_NS::shared_ptr<UnderlyingType>;
105     using WeakPtr = BASE_NS::weak_ptr<UnderlyingType>;
106     using IInterfacePtr = BASE_NS::shared_ptr<CORE_NS::IInterface>;
107     InterfaceObject() = delete;
InterfaceObject(const Ptr & p)108     explicit InterfaceObject(const Ptr& p) noexcept : ptr_(p) {}
InterfaceObject(const IInterfacePtr & p)109     explicit InterfaceObject(const IInterfacePtr& p) : ptr_(interface_pointer_cast<UnderlyingType>(p)) {}
110     /// Assignment operator
111     auto& operator=(const IInterfacePtr& p) noexcept
112     {
113         ptr_ = interface_pointer_cast<UnderlyingType>(p);
114         return *this;
115     }
116     /// InterfaceObject<T> to BASE_NS::shared_ptr<T> operator
Ptr()117     operator Ptr() const noexcept
118     {
119         return ptr_;
120     }
121     /// InterfaceObject<T> to BASE_NS::shared_ptr<CORE_NS::IInterface> operator
IInterfacePtr()122     operator IInterfacePtr() const noexcept
123     {
124         return ptr_;
125     }
126     /// Return the underlying BASE_NS::shared_ptr<T>
GetPtr()127     Ptr GetPtr() const noexcept
128     {
129         return ptr_;
130     }
131     /// Return the underlying BASE_NS::shared_ptr<T> converted to BASE_NS::shared_ptr<Interface>
132     template<typename Interface>
GetPtr()133     BASE_NS::shared_ptr<Interface> GetPtr() const
134     {
135         return interface_pointer_cast<Interface>(ptr_);
136     }
137     /// Release the underlying object.
Release()138     void Release()
139     {
140         ptr_.reset();
141     }
142 
143 protected:
144     /// Helper method for safely calling a method from the underlying interface
145     template<typename Interface, typename Fn>
CallPtr(Fn && fn)146     auto CallPtr(Fn&& fn) const
147     {
148         auto* p = interface_cast<Interface>(ptr_);
149         using Result = BASE_NS::remove_reference_t<decltype(fn(*p))>;
150         if constexpr (!BASE_NS::is_void_v<Result>) {
151             return p ? fn(*p) : Result {};
152         } else if (p) {
153             fn(*p);
154         }
155     }
156 
GetInterfacePtr()157     CORE_NS::IInterface* GetInterfacePtr() const noexcept override
158     {
159         return ptr_.get();
160     }
161     Ptr ptr_;
162 };
163 
164 // InterfaceObject definition
165 #define META_INTERFACE_OBJECT(Class, BaseClass, Interface)                                   \
166     using ClassType = Class;                                                                 \
167     using BaseClassType = BaseClass;                                                         \
168     using InterfaceType = Interface;                                                         \
169     Class() = delete;                                                                        \
170     ~Class() override = default;                                                             \
171     explicit Class(const IInterfacePtr& p) : BaseClass(interface_pointer_cast<Interface>(p)) \
172     {}                                                                                       \
173     META_DEFAULT_COPY_MOVE(Class)                                                            \
174     operator InterfaceType::Ptr() const noexcept                                             \
175     {                                                                                        \
176         return GetPtr<InterfaceType>();                                                      \
177     }                                                                                        \
178     auto& operator=(const InterfaceType::Ptr& p) noexcept                                    \
179     {                                                                                        \
180         ptr_ = interface_pointer_cast<UnderlyingType>(p);                                    \
181         return *this;                                                                        \
182     }
183 
184 // InterfaceObject default interface function call wrapper
185 #define META_INTERFACE_OBJECT_CALL_PTR(Function) CallPtr<InterfaceType>([&](auto& p) { return p.Function; })
186 
187 #define META_INTERFACE_OBJECT_PROPERTY_ACCESSOR(PropertyName)  \
188 public:                                                        \
189     auto PropertyName() const                                  \
190     {                                                          \
191         return META_INTERFACE_OBJECT_CALL_PTR(PropertyName()); \
192     }
193 
194 // InterfaceObject default readonly property wrapper
195 #define META_INTERFACE_OBJECT_READONLY_PROPERTY(Type, PropertyName) \
196     META_INTERFACE_OBJECT_PROPERTY_ACCESSOR(PropertyName)           \
197     auto Get##PropertyName() const                                  \
198     {                                                               \
199         return Type(META_NS::GetValue(PropertyName()));             \
200     }
201 
202 // InterfaceObject default property wrapper
203 #define META_INTERFACE_OBJECT_PROPERTY(Type, PropertyName)      \
204     META_INTERFACE_OBJECT_READONLY_PROPERTY(Type, PropertyName) \
205     auto& Set##PropertyName(const Type& value)                  \
206     {                                                           \
207         if (auto pr = PropertyName()) {                         \
208             pr->SetValue(value);                                \
209         }                                                       \
210         return *this;                                           \
211     }
212 
213 // InterfaceObject default readonly array property wrapper
214 #define META_INTERFACE_OBJECT_READONLY_ARRAY_PROPERTY(Type, PropertyName, AccessorName)                   \
215     META_INTERFACE_OBJECT_PROPERTY_ACCESSOR(PropertyName)                                                 \
216     auto Get##PropertyName() const                                                                        \
217     {                                                                                                     \
218         auto pr = PropertyName();                                                                         \
219         using ReturnType = decltype(pr->GetValue());                                                      \
220         auto value = pr ? pr->GetValue() : ReturnType {};                                                 \
221         return META_NS::Internal::ArrayCast<Type, typename ReturnType::value_type>(BASE_NS::move(value)); \
222     }                                                                                                     \
223     auto Get##AccessorName##Count() const                                                                 \
224     {                                                                                                     \
225         auto pr = PropertyName();                                                                         \
226         return pr ? pr->GetSize() : 0;                                                                    \
227     }                                                                                                     \
228     auto Get##AccessorName##At(size_t index) const                                                        \
229     {                                                                                                     \
230         auto pr = PropertyName();                                                                         \
231         return Type(pr ? pr->GetValueAt(index) : decltype(pr->GetValueAt(index)) {});                     \
232     }
233 
234 // InterfaceObject default array property wrapper
235 #define META_INTERFACE_OBJECT_ARRAY_PROPERTY(Type, PropertyName, AccessorName)      \
236     META_INTERFACE_OBJECT_READONLY_ARRAY_PROPERTY(Type, PropertyName, AccessorName) \
237     auto& Set##PropertyName(BASE_NS::array_view<const Type> value)                  \
238     {                                                                               \
239         if (auto pr = PropertyName()) {                                             \
240             pr->SetValue(value);                                                    \
241         }                                                                           \
242         return *this;                                                               \
243     }                                                                               \
244     auto& Set##AccessorName##At(size_t index, const Type& value)                    \
245     {                                                                               \
246         if (auto pr = PropertyName()) {                                             \
247             pr->SetValueAt(index, value);                                           \
248         }                                                                           \
249         return *this;                                                               \
250     }
251 
252 struct InitializationType {};
253 
254 /**
255  * @brief Some interface wrappers support creating an instance at wrapper object initialization.
256  *        Such classes can be made to automatically initialize the underlying object to a new class
257  *        instance defining Instanate
258  * @code
259  *        using namespace META_NS;
260  *        Object o(CreateNew); // Create a new instance of the underlying object suitable for this class.
261  * @endcode
262  */
263 constexpr InitializationType CreateNew;
264 
265 #define META_INTERFACE_OBJECT_INSTANTIATE(Class, ClassId)                                                 \
266     Class(const META_NS::InitializationType& t) : BaseClassType(::META_NS::CreateObjectInstance(ClassId)) \
267     {}
268 
269 /// Some methods support specifying whether the call should be asynchronous or synchronous through AsyncCallType
270 /// template parameter.
271 struct AsyncCallType {
272     bool async {};
273 };
274 /// Call should be synchronous and directly return the asynchronous call return value.
275 constexpr AsyncCallType Sync { false };
276 /// Call should be asynchronous and return a Future object as its return value.
277 constexpr AsyncCallType Async { true };
278 
279 #define META_API_ASYNC template<const META_NS::AsyncCallType& CallType = META_NS::Sync>
280 
281 #define META_INTERFACE_OBJECT_ASYNC_CALL_PTR(SyncReturnType, Function) \
282     [&]() -> auto                                                      \
283     {                                                                  \
284         auto f = META_INTERFACE_OBJECT_CALL_PTR(Function);             \
285         if constexpr (CallType.async) {                                \
286             return f;                                                  \
287         } else {                                                       \
288             return SyncReturnType(f.GetResult());                      \
289         }                                                              \
290     }                                                                  \
291     ()
292 
META_END_NAMESPACE()293 META_END_NAMESPACE()
294 
295 // NOLINTBEGIN(readability-identifier-naming) to keep std like syntax
296 
297 template<typename T, typename S>
298 BASE_NS::shared_ptr<T> interface_pointer_cast(const META_NS::InterfaceObject<S>& io)
299 {
300     static_assert(META_NS::HasGetInterfaceMethod_v<T>, "T::GetInterface not defined");
301     return interface_pointer_cast<T>(io.GetPtr());
302 }
303 
304 template<typename T, typename S>
interface_cast(const META_NS::InterfaceObject<S> & io)305 T* interface_cast(const META_NS::InterfaceObject<S>& io)
306 {
307     static_assert(META_NS::HasGetInterfaceMethod_v<T>, "T::GetInterface not defined");
308     return interface_cast<T>(io.GetPtr());
309 }
310 
311 // NOLINTEND(readability-identifier-naming) to keep std like syntax
312 
313 #endif // META_API_INTERFACE_OBJECT_H
314