1 /*
2 * Copyright (c) 2022 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 API_CORE_PLUGIN_IINTERFACE_H
17 #define API_CORE_PLUGIN_IINTERFACE_H
18
19 #include <base/containers/refcnt_ptr.h>
20 #include <base/containers/shared_ptr.h>
21 #include <base/namespace.h>
22 #include <base/util/uid.h>
23 #include <core/namespace.h>
24
CORE_BEGIN_NAMESPACE()25 CORE_BEGIN_NAMESPACE()
26 /** Base type for named interfaces provided by plugin.
27 */
28 class IInterface {
29 public:
30 static constexpr BASE_NS::Uid UID { "00000000-0000-0000-0000-000000000000" };
31
32 using Ptr = BASE_NS::refcnt_ptr<IInterface>;
33
34 /** Access to provided sub-interfaces
35 */
36 virtual const IInterface* GetInterface(const BASE_NS::Uid& uid) const = 0;
37 virtual IInterface* GetInterface(const BASE_NS::Uid& uid) = 0;
38
39 template<typename InterfaceType>
40 const InterfaceType* GetInterface() const
41 {
42 return static_cast<const InterfaceType*>(GetInterface(InterfaceType::UID));
43 }
44
45 template<typename InterfaceType>
46 InterfaceType* GetInterface()
47 {
48 return static_cast<InterfaceType*>(GetInterface(InterfaceType::UID));
49 }
50
51 /** Take a new reference of the object.
52 */
53 virtual void Ref() = 0;
54
55 /* Releases one reference of the object.
56 * No methods of the class shall be called after unref.
57 * The object could be destroyed, if last reference
58 */
59 virtual void Unref() = 0;
60
61 protected:
62 IInterface() = default;
63 virtual ~IInterface() = default;
64 };
CORE_END_NAMESPACE()65 CORE_END_NAMESPACE()
66
67 // NOLINTBEGIN(readability-identifier-naming) to keep std like syntax
68 template<class U, class T>
69 BASE_NS::shared_ptr<U> interface_pointer_cast(const BASE_NS::shared_ptr<T>& ptr)
70 {
71 static_assert(BASE_NS::is_base_of_v<CORE_NS::IInterface, T>, "T is not an IInterface");
72 static_assert(BASE_NS::is_base_of_v<CORE_NS::IInterface, U>, "U is not an IInterface");
73 if (ptr) {
74 if constexpr (BASE_NS::is_same_v<U, T>) {
75 // same type.
76 return ptr;
77 } else {
78 return BASE_NS::shared_ptr<U>(ptr, static_cast<U*>(static_cast<void*>(ptr->GetInterface(U::UID))));
79 }
80 }
81 return {};
82 }
83
84 template<class U, class T>
interface_pointer_cast(const BASE_NS::shared_ptr<const T> & ptr)85 BASE_NS::shared_ptr<const U> interface_pointer_cast(const BASE_NS::shared_ptr<const T>& ptr)
86 {
87 static_assert(BASE_NS::is_base_of_v<CORE_NS::IInterface, T>, "T is not an IInterface");
88 static_assert(BASE_NS::is_base_of_v<CORE_NS::IInterface, U>, "U is not an IInterface");
89 if (ptr) {
90 if constexpr (BASE_NS::is_same_v<U, T>) {
91 // same type.
92 return ptr;
93 } else {
94 return BASE_NS::shared_ptr<const U>(
95 ptr, static_cast<const U*>(static_cast<const void*>(ptr->GetInterface(U::UID))));
96 }
97 }
98 return {};
99 }
100
101 template<class U, class T>
interface_pointer_cast(const BASE_NS::weak_ptr<T> & weak)102 BASE_NS::shared_ptr<U> interface_pointer_cast(const BASE_NS::weak_ptr<T>& weak)
103 {
104 return interface_pointer_cast<U>(weak.lock());
105 }
106
107 template<class U, class T>
interface_pointer_cast(const BASE_NS::weak_ptr<const T> & weak)108 BASE_NS::shared_ptr<const U> interface_pointer_cast(const BASE_NS::weak_ptr<const T>& weak)
109 {
110 return interface_pointer_cast<const U>(weak.lock());
111 }
112
113 template<class U, class T>
interface_cast(const BASE_NS::shared_ptr<T> & ptr)114 U* interface_cast(const BASE_NS::shared_ptr<T>& ptr)
115 {
116 static_assert(BASE_NS::is_base_of_v<CORE_NS::IInterface, T>, "T is not an IInterface");
117 static_assert(BASE_NS::is_base_of_v<CORE_NS::IInterface, U>, "U is not an IInterface");
118 if (ptr) {
119 if constexpr (BASE_NS::is_same_v<U, T>) {
120 // same type.
121 return ptr.get();
122 } else {
123 return static_cast<U*>(static_cast<void*>(ptr->GetInterface(U::UID)));
124 }
125 }
126 return {};
127 }
128
129 template<class U, class T>
interface_cast(const BASE_NS::shared_ptr<const T> & ptr)130 const U* interface_cast(const BASE_NS::shared_ptr<const T>& ptr)
131 {
132 static_assert(BASE_NS::is_base_of_v<CORE_NS::IInterface, T>, "T is not an IInterface");
133 static_assert(BASE_NS::is_base_of_v<CORE_NS::IInterface, U>, "U is not an IInterface");
134 if (ptr) {
135 if constexpr (BASE_NS::is_same_v<U, T>) {
136 // same type.
137 return ptr.get();
138 } else {
139 return static_cast<const U*>(static_cast<const void*>(ptr->GetInterface(U::UID)));
140 }
141 }
142 return {};
143 }
144
145 template<class U>
interface_cast(CORE_NS::IInterface * ptr)146 U* interface_cast(CORE_NS::IInterface* ptr)
147 {
148 static_assert(BASE_NS::is_base_of_v<CORE_NS::IInterface, U>, "U is not an IInterface");
149 if (ptr) {
150 return static_cast<U*>(static_cast<void*>(ptr->GetInterface(U::UID)));
151 }
152 return {};
153 }
154
155 template<class U>
interface_cast(const CORE_NS::IInterface * ptr)156 const U* interface_cast(const CORE_NS::IInterface* ptr)
157 {
158 static_assert(BASE_NS::is_base_of_v<CORE_NS::IInterface, U>, "U is not an IInterface");
159 if (ptr) {
160 return static_cast<const U*>(static_cast<const void*>(ptr->GetInterface(U::UID)));
161 }
162 return {};
163 }
164 // NOLINTEND(readability-identifier-naming) to keep std like syntax
165 #endif // API_CORE_PLUGIN_IINTERFACE_H
166