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_EXT_IMPLEMENTATION_MACROS_H
17 #define META_EXT_IMPLEMENTATION_MACROS_H
18
19 #include <meta/base/namespace.h>
20 #include <meta/base/shared_ptr.h>
21 #include <meta/ext/event_impl.h>
22 #include <meta/interface/interface_macros.h>
23 #include <meta/interface/intf_object_flags.h>
24 #include <meta/interface/property/construct_array_property.h>
25 #include <meta/interface/property/construct_property.h>
26
27 /**
28 * @brief Access property variable introduced with META_IMPLEMENT_*_PROPERTY
29 */
30 #define META_ACCESS_PROPERTY(name) metaProperty##name##_
31 #define META_ACCESS_PROPERTY_VALUE(name) metaProperty##name##_->GetValue()
32 /**
33 * @brief Access event variable introduced with META_IMPLEMENT_*_EVENT
34 */
35 #define META_ACCESS_EVENT(name) metaEvent##name##_
36
37 #define META_VALUE_PTR(interface, classId) ::META_NS::ValuePtrImpl<interface>::Instance<classId>
38
META_BEGIN_NAMESPACE()39 META_BEGIN_NAMESPACE()
40 constexpr ObjectFlagBitsValue DEFAULT_PROPERTY_FLAGS = ObjectFlagBitsValue { ObjectFlagBits::SERIALIZE };
41 constexpr ObjectFlagBitsValue DEFAULT_PROPERTY_FLAGS_NO_SER = ObjectFlagBitsValue { ObjectFlagBits::NONE };
42 META_END_NAMESPACE()
43
44 #define META_DEFINE_PROPERTY_VAR(intf, name, type, defaultValue, flags) \
45 ::META_NS::Property<::META_NS::PropertyType_v<type>> metaProperty##name##_ = \
46 this->template RegisterStaticPropertyMetadata<::META_NS::PropertyType_v<type>>( \
47 intf, #name, flags, \
48 [] { return ::META_NS::IProperty::Ptr(::META_NS::ConstructProperty<type>(#name, defaultValue, flags)); }, \
49 [](auto me) { /*workaround for older msvc not supporting decltype(this) without capture*/ \
50 return [](void* self, const ::META_NS::IProperty::Ptr& p) { \
51 if (p) { \
52 static_cast<decltype(me)>(self)->metaProperty##name##_ = p; \
53 } \
54 return p != nullptr; \
55 }; \
56 }(this));
57
58 #define META_DEFINE_PROPERTY_VARArray(intf, name, type, defaultValue, flags) \
59 ::META_NS::ArrayProperty<type> metaProperty##name##_ = this->template RegisterStaticPropertyMetadata<type[]>( \
60 intf, #name, flags, \
61 [] { return ::META_NS::IProperty::Ptr(::META_NS::ConstructArrayProperty<type>(#name, defaultValue, flags)); }, \
62 [](auto me) { /*workaround for older msvc not supporting decltype(this) without capture*/ \
63 return [](void* self, const ::META_NS::IProperty::Ptr& p) { \
64 if (p) { \
65 static_cast<decltype(me)>(self)->metaProperty##name##_ = p; \
66 } \
67 return p != nullptr; \
68 }; \
69 }(this));
70
71 #define META_DEFINE_READONLY_PROPERTY(propType, intf, name, type, defaultValue, flags) \
72 META_DEFINE_PROPERTY_VAR##propType( \
73 intf, name, type, defaultValue, flags)::META_NS::IProperty::ConstPtr Property##name() const noexcept override \
74 { \
75 return metaProperty##name##_; \
76 } \
77 META_READONLY_PROPERTY_TYPED_IMPL(::META_NS::PropertyType_v<type>, name)
78
79 #define META_DEFINE_PROPERTY(propType, intf, name, type, defaultValue, flags) \
80 META_DEFINE_READONLY_PROPERTY(propType, intf, name, type, defaultValue, flags) \
81 ::META_NS::IProperty::Ptr Property##name() noexcept override \
82 { \
83 return metaProperty##name##_; \
84 } \
85 META_PROPERTY_TYPED_IMPL(::META_NS::PropertyType_v<type>, name)
86
87 #define META_DEFINE_READONLY_ARRAY_PROPERTY(propType, intf, name, type, defaultValue, flags) \
88 META_DEFINE_PROPERTY_VAR##propType( \
89 intf, name, type, defaultValue, flags)::META_NS::IProperty::ConstPtr Property##name() const noexcept override \
90 { \
91 return metaProperty##name##_; \
92 } \
93 META_READONLY_ARRAY_PROPERTY_TYPED_IMPL(type, name)
94
95 #define META_DEFINE_ARRAY_PROPERTY(propType, intf, name, type, defaultValue, flags) \
96 META_DEFINE_READONLY_ARRAY_PROPERTY(propType, intf, name, type, defaultValue, flags) \
97 ::META_NS::IProperty::Ptr Property##name() noexcept override \
98 { \
99 return metaProperty##name##_; \
100 } \
101 META_ARRAY_PROPERTY_TYPED_IMPL(type, name)
102
103 #define META_GET_PROPERTY4(macro, propType, intf, type, name, defaultValue, flags) \
104 macro(propType, intf, name, type, defaultValue, \
105 ::META_NS::ObjectFlagBitsValue { flags } | ::META_NS::ObjectFlagBits::NATIVE)
106 #define META_GET_PROPERTY3(macro, propType, intf, type, name, defaultValue) \
107 macro(propType, intf, name, type, defaultValue, \
108 ::META_NS::DEFAULT_PROPERTY_FLAGS | ::META_NS::ObjectFlagBits::NATIVE)
109 #define META_GET_PROPERTY2(macro, propType, intf, type, name) \
110 macro(propType, intf, name, type, {}, ::META_NS::DEFAULT_PROPERTY_FLAGS | ::META_NS::ObjectFlagBits::NATIVE)
111 #define META_GET_PROPERTY(macro, propType, ...) \
112 META_EXPAND(META_GET_MACRO5_IMPL(__VA_ARGS__, META_GET_PROPERTY4, META_GET_PROPERTY3, META_GET_PROPERTY2)( \
113 macro, propType, __VA_ARGS__))
114
115 /**
116 * @brief Implement property that was introduced using META_PROPERTY in interface.
117 * This will add the property to static metadata and generates code to construct
118 * it when the object is constructed.
119 */
120 #define META_IMPLEMENT_PROPERTY(...) \
121 META_EXPAND(META_GET_PROPERTY(META_DEFINE_PROPERTY,, META_NS::InterfaceInfo {}, __VA_ARGS__))
122 #define META_IMPLEMENT_READONLY_PROPERTY(...) \
123 META_EXPAND(META_GET_PROPERTY(META_DEFINE_READONLY_PROPERTY,, META_NS::InterfaceInfo {}, __VA_ARGS__))
124 #define META_IMPLEMENT_ARRAY_PROPERTY(...) \
125 META_EXPAND(META_GET_PROPERTY(META_DEFINE_ARRAY_PROPERTY, Array, META_NS::InterfaceInfo {}, __VA_ARGS__))
126 #define META_IMPLEMENT_READONLY_ARRAY_PROPERTY(...) \
127 META_EXPAND(META_GET_PROPERTY(META_DEFINE_READONLY_ARRAY_PROPERTY, Array, META_NS::InterfaceInfo {}, __VA_ARGS__))
128
129 /**
130 * @brief Same as META_IMPLEMENT_PROPERTY but first parameter tells which interface introduced this property.
131 */
132 #define META_IMPLEMENT_INTERFACE_PROPERTY(intf, ...) \
133 META_EXPAND(META_GET_PROPERTY(META_DEFINE_PROPERTY,, intf::INTERFACE_INFO, __VA_ARGS__))
134 #define META_IMPLEMENT_INTERFACE_READONLY_PROPERTY(intf, ...) \
135 META_EXPAND(META_GET_PROPERTY(META_DEFINE_READONLY_PROPERTY,, intf::INTERFACE_INFO, __VA_ARGS__))
136 #define META_IMPLEMENT_INTERFACE_ARRAY_PROPERTY(intf, ...) \
137 META_EXPAND(META_GET_PROPERTY(META_DEFINE_ARRAY_PROPERTY, Array, intf::INTERFACE_INFO, __VA_ARGS__))
138 #define META_IMPLEMENT_INTERFACE_READONLY_ARRAY_PROPERTY(intf, ...) \
139 META_EXPAND(META_GET_PROPERTY(META_DEFINE_READONLY_ARRAY_PROPERTY, Array, intf::INTERFACE_INFO, __VA_ARGS__))
140
141 /**
142 * @brief Make forwarding function for the read-only property.
143 */
144 #define META_FORWARD_READONLY_PROPERTY(type, name, forwarder) \
145 META_NS::IProperty::ConstPtr Property##name() const noexcept override \
146 { \
147 return forwarder; \
148 } \
149 META_READONLY_PROPERTY_TYPED_IMPL(type, name)
150
151 /**
152 * @brief Make forwarding function for the property.
153 */
154 #define META_FORWARD_PROPERTY(type, name, forwarder) \
155 META_FORWARD_READONLY_PROPERTY(type, name, forwarder) \
156 META_NS::IProperty::Ptr Property##name() noexcept override \
157 { \
158 return forwarder; \
159 } \
160 META_PROPERTY_TYPED_IMPL(type, name)
161
162 #define META_FORWARD_BASE_READONLY_PROPERTY(type, name) \
163 META_FORWARD_READONLY_PROPERTY(type, name, this->Super::Property##name())
164
165 #define META_FORWARD_BASE_PROPERTY(type, name) META_FORWARD_PROPERTY(type, name, this->Super::Property##name())
166
167 #define META_FORWARD_READONLY_ARRAY_PROPERTY(type, name, forwarder) \
168 META_NS::IProperty::ConstPtr Property##name() const noexcept override \
169 { \
170 return forwarder; \
171 } \
172 META_READONLY_ARRAY_PROPERTY_TYPED_IMPL(type, name)
173
174 /**
175 * @brief Make forwarding function for the property.
176 */
177 #define META_FORWARD_ARRAY_PROPERTY(type, name, forwarder) \
178 META_FORWARD_READONLY_ARRAY_PROPERTY(type, name, forwarder) \
179 META_NS::IProperty::Ptr Property##name() noexcept override \
180 { \
181 return forwarder; \
182 } \
183 META_ARRAY_PROPERTY_TYPED_IMPL(type, name)
184
185 #define META_FORWARD_BASE_READONLY_ARRAY_PROPERTY(type, name) \
186 META_FORWARD_READONLY_ARRAY_PROPERTY(type, name, this->Super::Property##name())
187
188 #define META_FORWARD_BASE_ARRAY_PROPERTY(type, name) \
189 META_FORWARD_ARRAY_PROPERTY(type, name, this->Super::Property##name())
190
191 #define META_DEFINE_EVENT_VAR(intf, type, name) \
192 mutable BASE_NS::shared_ptr<::META_NS::EventImpl<type>> metaEvent##name##_ = \
193 this->template RegisterStaticEventMetadata<type>( \
194 intf, #name, [] { return ::META_NS::IEvent::Ptr(CreateShared<::META_NS::EventImpl<type>>(#name)); }, \
195 [](auto me) { /*workaround for older msvc not supporting decltype(this) without capture*/ \
196 return [](void* self, const ::META_NS::IEvent::Ptr& p) { \
197 if (p->GetCallableUid() == type::UID) { \
198 /* notice this is dangerous if same UID used for many different event types*/ \
199 static_cast<decltype(me)>(self)->metaEvent##name##_ = \
200 static_pointer_cast<::META_NS::EventImpl<type>>(p); \
201 return true; \
202 } \
203 return false; \
204 }; \
205 }(this));
206
207 #define META_DEFINE_EVENT(intf, itype, etype, name) \
208 META_DEFINE_EVENT_VAR(intf, etype, name) \
209 BASE_NS::shared_ptr<::META_NS::IEvent> Event##name() const override \
210 { \
211 CORE_ASSERT_MSG(metaEvent##name##_, "Metadata not initialized"); \
212 return metaEvent##name##_; \
213 } \
214 META_EVENT_TYPED_IMPL(itype, name)
215
216 #define META_GET_EVENT3(intf, itype, etype, name) META_DEFINE_EVENT(intf, itype, etype, name)
217 #define META_GET_EVENT2(intf, etype, name) META_DEFINE_EVENT(intf, etype, etype, name)
218 #define META_GET_EVENT(...) \
219 META_EXPAND(META_GET_MACRO4_IMPL(__VA_ARGS__, META_GET_EVENT3, META_GET_EVENT2)(__VA_ARGS__))
220
221 /**
222 * @brief Implement event that was introduced using META_PROPERTY in interface.
223 * This will add the event to static metadata and generates code to construct
224 * it when the object is constructed.
225 */
226 #define META_IMPLEMENT_EVENT(...) META_EXPAND(META_GET_EVENT(META_NS::InterfaceInfo {}, __VA_ARGS__))
227 /**
228 * @brief Same as META_IMPLEMENT_EVENT but first parameter tells which interface introduced this event.
229 */
230 #define META_IMPLEMENT_INTERFACE_EVENT(intf, ...) META_EXPAND(META_GET_EVENT(intf::INTERFACE_INFO, __VA_ARGS__))
231
232 #define META_FORWARD_EVENT(type, name, forwarder) \
233 BASE_NS::shared_ptr<::META_NS::IEvent> Event##name() const override \
234 { \
235 return forwarder; \
236 } \
237 META_EVENT_TYPED_IMPL(type, name)
238
239 #define META_FORWARD_EVENT_CLASS(type, name, targetClass) \
240 BASE_NS::shared_ptr<::META_NS::IEvent> Event##name() const override \
241 { \
242 return targetClass::Event##name(); \
243 } \
244 ::META_NS::Event<type> name() const \
245 { \
246 return targetClass::Event##name(); \
247 }
248
249 #define META_DEFINE_FUNCTION_VAR(intf, class, func, ...) \
250 mutable ::META_NS::IFunction::Ptr metaFunc##func##_ = this->RegisterStaticFunctionMetadata( \
251 intf, #func, \
252 [](auto me) { \
253 return [](void* self) { \
254 auto ccontext = []() { \
255 ::BASE_NS::string_view arr[] = { "", __VA_ARGS__ }; \
256 return CreateCallContext(&class ::func, ::META_NS::ParamNameToView(arr)); \
257 }; \
258 return ::META_NS::IFunction::Ptr(::META_NS::CreateFunction( \
259 #func, static_cast<decltype(me)>(self), &class ::func##MetaImpl, ccontext)); \
260 }; \
261 }(this), \
262 []() { \
263 /*cannot have zero size array, so we add something in front and ParamNameToView removes it*/ \
264 BASE_NS::string_view arr[] = { "", __VA_ARGS__ }; \
265 return ::META_NS::CreateCallContext(&class ::func, ::META_NS::ParamNameToView(arr)); \
266 });
267
268 #define META_DEFINE_IMPL_FUNCTION(class, func) \
269 void func##MetaImpl(const ::META_NS::ICallContext::Ptr& context) \
270 { \
271 ::META_NS::CallFunction(context, this, &class ::func); \
272 }
273
274 #define META_IMPLEMENT_PLAIN_FUNCTION(class, func, ...) \
275 META_DEFINE_FUNCTION_VAR(META_NS::InterfaceInfo {}, class, func, __VA_ARGS__)
276
277 #define META_IMPLEMENT_FUNCTION(class, func, ...) \
278 META_IMPLEMENT_PLAIN_FUNCTION(class, func, __VA_ARGS__) \
279 META_DEFINE_IMPL_FUNCTION(class, func)
280
281 #define META_IMPLEMENT_INTERFACE_PLAIN_FUNCTION(interface, class, func, ...) \
282 META_DEFINE_FUNCTION_VAR(interface::INTERFACE_INFO, class, func, __VA_ARGS__)
283
284 #define META_IMPLEMENT_INTERFACE_FUNCTION(interface, class, func, ...) \
285 META_IMPLEMENT_INTERFACE_PLAIN_FUNCTION(interface, class, func, __VA_ARGS__) \
286 META_DEFINE_IMPL_FUNCTION(class, func)
287
288 #endif
289