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