• 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_EXT_IMPLEMENTATION_MACROS_H
17 #define META_EXT_IMPLEMENTATION_MACROS_H
18 
19 #include <base/containers/shared_ptr.h>
20 
21 #include <meta/base/namespace.h>
22 #include <meta/ext/event_impl.h>
23 #include <meta/ext/object_factory.h>
24 #include <meta/interface/interface_macros.h>
25 #include <meta/interface/intf_object_flags.h>
26 #include <meta/interface/intf_object_registry.h>
27 #include <meta/interface/intf_owner.h>
28 #include <meta/interface/metadata_query.h>
29 #include <meta/interface/property/construct_array_property.h>
30 #include <meta/interface/property/construct_property.h>
31 
32 /**
33  * @brief Access property variable introduced with META_IMPLEMENT_*_PROPERTY
34  */
35 #define META_ACCESS_PROPERTY(name) name()
36 #define META_ACCESS_PROPERTY_VALUE(name) name()->GetValue()
37 /**
38  * @brief Access event variable introduced with META_IMPLEMENT_*_EVENT
39  */
40 #define META_ACCESS_EVENT(name) name()
41 
42 #define META_VALUE_PTR(interface, classId) ::META_NS::ValuePtrImpl<interface>::Instance<classId>
43 
META_BEGIN_NAMESPACE()44 META_BEGIN_NAMESPACE()
45 constexpr ObjectFlagBitsValue DEFAULT_PROPERTY_FLAGS = ObjectFlagBitsValue { ObjectFlagBits::SERIALIZE };
46 constexpr ObjectFlagBitsValue DEFAULT_PROPERTY_FLAGS_NO_SER = ObjectFlagBitsValue { ObjectFlagBits::NONE };
47 
48 template<typename Type>
CreatePropertyImpl(BASE_NS::string_view name,Internal::MetaValue * def,ObjectFlagBitsValue flags)49 IProperty::Ptr CreatePropertyImpl(BASE_NS::string_view name, Internal::MetaValue* def, ObjectFlagBitsValue flags)
50 {
51     flags |= ObjectFlagBits::NATIVE;
52     IAny::Ptr value;
53     if (def) {
54         value = def();
55     }
56     if constexpr (BASE_NS::is_array_v<Type>) {
57         if (value) {
58             return META_NS::ConstructArrayPropertyAny<BASE_NS::remove_extent_t<Type>>(name, *value, flags);
59         }
60         return META_NS::ConstructArrayProperty<BASE_NS::remove_extent_t<Type>>(name, {}, flags);
61     } else {
62         if (value) {
63             return META_NS::ConstructPropertyAny<Type>(name, *value, flags);
64         }
65         return META_NS::ConstructProperty<Type>(name, {}, flags);
66     }
67 }
68 
69 template<typename Type, uint64_t Flags>
CreatePropertyConstructor()70 Internal::MetadataCtor* CreatePropertyConstructor()
71 {
72     return [](const BASE_NS::shared_ptr<IOwner>& owner, const StaticMetadata& d) {
73         auto ret = interface_pointer_cast<CORE_NS::IInterface>(
74             META_NS::CreatePropertyImpl<Type>(d.name, d.runtimeValue, ObjectFlagBitsValue(Flags)));
75         if (ret) {
76             if (auto ctor = interface_cast<IMetadataOwner>(owner)) {
77                 ctor->OnMetadataConstructed(d, *ret);
78             }
79         }
80         return ret;
81     };
82 }
83 
84 template<typename Type>
CreateEventConstructor()85 Internal::MetadataCtor* CreateEventConstructor()
86 {
87     return [](const BASE_NS::shared_ptr<IOwner>& owner, const StaticMetadata& d) {
88         auto ret = interface_pointer_cast<CORE_NS::IInterface>(CreateShared<EventImpl<Type>>(d.name));
89         if (ret) {
90             if (auto ctor = interface_cast<IMetadataOwner>(owner)) {
91                 ctor->OnMetadataConstructed(d, *ret);
92             }
93         }
94         return ret;
95     };
96 }
97 
98 template<typename Interface, auto MemFun>
CreateFunctionConstructor()99 Internal::MetadataCtor* CreateFunctionConstructor()
100 {
101     return [](const BASE_NS::shared_ptr<IOwner>& owner, const StaticMetadata& d) {
102         auto ret = interface_pointer_cast<CORE_NS::IInterface>(
103             CreateFunction(d.name, interface_pointer_cast<Interface>(owner), MemFun, d.runtimeValue));
104         if (ret) {
105             if (auto ctor = interface_cast<IMetadataOwner>(owner)) {
106                 ctor->OnMetadataConstructed(d, *ret);
107             }
108         }
109         return ret;
110     };
111 }
112 
113 template<size_t Size>
MetadataArraySize(const StaticMetadata (&)[Size])114 constexpr size_t MetadataArraySize(const StaticMetadata (&)[Size])
115 {
116     return Size;
117 }
MetadataArraySize(const nullptr_t &)118 constexpr size_t MetadataArraySize(const nullptr_t&)
119 {
120     return 0;
121 }
122 
GetAggregateMetadata(const ObjectId & id)123 inline const StaticObjectMetadata* GetAggregateMetadata(const ObjectId& id)
124 {
125     auto f = GetObjectRegistry().GetObjectFactory(id);
126     return f ? f->GetClassStaticMetadata() : nullptr;
127 }
128 
129 template<typename Type, typename Base, typename Data>
CreateStaticMetadata(const Data & data,const StaticObjectMetadata * base,const ClassInfo * classInfo,const StaticObjectMetadata * aggregate)130 inline StaticObjectMetadata CreateStaticMetadata(const Data& data, const StaticObjectMetadata* base,
131     const ClassInfo* classInfo, const StaticObjectMetadata* aggregate)
132 {
133     size_t size = META_NS::MetadataArraySize(data);
134     bool baseDataSame = size && base && data == base->metadata;
135     return StaticObjectMetadata { classInfo, base, aggregate, baseDataSame ? nullptr : data, baseDataSame ? 0 : size };
136 }
137 
138 template<typename T>
GetPropertySMDFlags(BASE_NS::shared_ptr<META_NS::IProperty> (T::*)(),int)139 inline uint8_t GetPropertySMDFlags(BASE_NS::shared_ptr<META_NS::IProperty> (T::*)(), int)
140 {
141     return 0;
142 }
143 
144 template<typename T>
GetPropertySMDFlags(BASE_NS::shared_ptr<const META_NS::IProperty> (T::*)()const,short)145 inline uint8_t GetPropertySMDFlags(BASE_NS::shared_ptr<const META_NS::IProperty> (T::*)() const, short)
146 {
147     return static_cast<uint8_t>(Internal::PropertyFlag::READONLY);
148 }
149 
150 META_END_NAMESPACE()
151 
152 #define META_IMPLEMENT_STATIC_DATA_DEPIMPL(myClass, classInfo, baseClass)                                       \
153 private:                                                                                                        \
154     using Super = baseClass;                                                                                    \
155                                                                                                                 \
156 public:                                                                                                         \
157     static const META_NS::StaticObjectMetadata* StaticMetadata()                                                \
158     {                                                                                                           \
159         static const META_NS::StaticObjectMetadata objdata { META_NS::CreateStaticMetadata<myClass, baseClass>( \
160             myClass::STATIC_METADATA, baseClass::StaticMetadata(), classInfo, nullptr) };                       \
161         return &objdata;                                                                                        \
162     }                                                                                                           \
163     const META_NS::StaticObjectMetadata* GetStaticMetadata() const override                                     \
164     {                                                                                                           \
165         return StaticMetadata();                                                                                \
166     }
167 
168 #define META_IMPLEMENT_STATIC_DATA_AGGRIMPL(myClass, classInfo, baseClass, aggrClass)                           \
169 private:                                                                                                        \
170     using Super = baseClass;                                                                                    \
171                                                                                                                 \
172 public:                                                                                                         \
173     static const META_NS::StaticObjectMetadata* StaticMetadata()                                                \
174     {                                                                                                           \
175         static const META_NS::StaticObjectMetadata objdata { META_NS::CreateStaticMetadata<myClass, baseClass>( \
176             myClass::STATIC_METADATA, baseClass::StaticMetadata(), classInfo,                                   \
177             META_NS::GetAggregateMetadata(aggrClass)) };                                                        \
178         return &objdata;                                                                                        \
179     }                                                                                                           \
180     const META_NS::StaticObjectMetadata* GetStaticMetadata() const override                                     \
181     {                                                                                                           \
182         return StaticMetadata();                                                                                \
183     }
184 
185 #define META_BEGIN_STATIC_DATA() inline static const META_NS::StaticMetadata STATIC_METADATA[] = {
186 #define META_END_STATIC_DATA() \
187     }                          \
188     ;
189 
190 #define META_IMPLEMENT_OBJECT_TYPE_INTERFACE(classInfo)          \
191     META_NS::ObjectId GetClassId() const override                \
192     {                                                            \
193         return classInfo.Id();                                   \
194     }                                                            \
195     BASE_NS::string_view GetClassName() const override           \
196     {                                                            \
197         return classInfo.Name();                                 \
198     }                                                            \
199     BASE_NS::vector<BASE_NS::Uid> GetInterfaces() const override \
200     {                                                            \
201         return GetInterfacesVector();                            \
202     }
203 
204 #define META_IMPLEMENT_OBJECT_BASE_AGGR(myClass, classInfo, baseClass, aggrClass)  \
205     META_IMPLEMENT_STATIC_DATA_AGGRIMPL(myClass, &classInfo, baseClass, aggrClass) \
206     META_IMPLEMENT_OBJECT_TYPE_INTERFACE(classInfo)                                \
207     META_DEFINE_OBJECT_TYPE_INFO(myClass, classInfo)
208 
209 #define META_IMPLEMENT_OBJECT_BASE(myClass, classInfo, baseClass)      \
210     META_IMPLEMENT_STATIC_DATA_DEPIMPL(myClass, &classInfo, baseClass) \
211     META_IMPLEMENT_OBJECT_TYPE_INTERFACE(classInfo)                    \
212     META_DEFINE_OBJECT_TYPE_INFO(myClass, classInfo)
213 
214 #define META_OBJECT(...) \
215     META_EXPAND(         \
216         META_GET_MACRO4_IMPL(__VA_ARGS__, META_IMPLEMENT_OBJECT_BASE_AGGR, META_IMPLEMENT_OBJECT_BASE)(__VA_ARGS__))
217 
218 #define META_IMPLEMENT_OBJECT_BASE_AGGR_NO_CLASSINFO(myClass, baseClass, aggrClass) \
219     META_IMPLEMENT_STATIC_DATA_AGGRIMPL(myClass, nullptr, baseClass, aggrClass)
220 
221 #define META_IMPLEMENT_OBJECT_BASE_NO_CLASSINFO(myClass, baseClass) \
222     META_IMPLEMENT_STATIC_DATA_DEPIMPL(myClass, nullptr, baseClass)
223 
224 #define META_OBJECT_NO_CLASSINFO(...)                                                           \
225     META_EXPAND(META_GET_MACRO3_IMPL(__VA_ARGS__, META_IMPLEMENT_OBJECT_BASE_AGGR_NO_CLASSINFO, \
226         META_IMPLEMENT_OBJECT_BASE_NO_CLASSINFO)(__VA_ARGS__))
227 
228 #define META_INTF_CHECK(interface, type, name) interface::INTERFACE_INFO
229 
230 // todo: check in META_STATIC_PROPERTY_DATA and META_STATIC_EVENT_DATA that name is part of the given interface
231 //--- PROPERTY DATA
232 #define META_IMPL_PROPERTY_DATA_VALUE_FLAGS_SMDF(intfuid, type, name, value, flags, smdflags)       \
233     { META_NS::MetadataType::PROPERTY, intfuid, #name,                                              \
234         META_NS::CreatePropertyConstructor<type, META_NS::ObjectFlagBitsValue(flags).GetValue()>(), \
235         [] { return META_NS::ConstructAnyHelper<type>(value); }, nullptr, smdflags },
236 
237 #define META_IMPL_PROPERTY_DATA_VALUE_FLAGS(intf, type, name, value, flags)                               \
238     META_IMPL_PROPERTY_DATA_VALUE_FLAGS_SMDF(META_INTF_CHECK(intf, type, name), type, name, value, flags, \
239         META_NS::GetPropertySMDFlags(&intf::Property##name, 0))
240 #define META_IMPL_PROPERTY_DATA_VALUE(intf, type, name, value) \
241     META_IMPL_PROPERTY_DATA_VALUE_FLAGS(intf, type, name, value, META_NS::DEFAULT_PROPERTY_FLAGS)
242 #define META_IMPL_PROPERTY_DATA(intf, type, name) META_IMPL_PROPERTY_DATA_VALUE(intf, type, name, {})
243 
244 #define META_STATIC_PROPERTY_DATA(...)                                                                                \
245     META_EXPAND(META_GET_MACRO5_IMPL(__VA_ARGS__, META_IMPL_PROPERTY_DATA_VALUE_FLAGS, META_IMPL_PROPERTY_DATA_VALUE, \
246         META_IMPL_PROPERTY_DATA)(__VA_ARGS__))
247 //---
248 
249 //--- ARRAY PROPERTY DATA
250 #define META_IMPL_ARRAY_PROPERTY_DATA_VALUE_FLAGS(intf, type, name, value, flags)                     \
251     { META_NS::MetadataType::PROPERTY, META_INTF_CHECK(intf, type, name), #name,                      \
252         META_NS::CreatePropertyConstructor<type[], META_NS::ObjectFlagBitsValue(flags).GetValue()>(), \
253         [] { return META_NS::IAny::Ptr(META_NS::ConstructArrayAnyHelper<type>(value)); } },
254 
255 #define META_IMPL_ARRAY_PROPERTY_DATA_VALUE(intf, type, name, value) \
256     META_IMPL_ARRAY_PROPERTY_DATA_VALUE_FLAGS(intf, type, name, value, META_NS::DEFAULT_PROPERTY_FLAGS)
257 #define META_IMPL_ARRAY_PROPERTY_DATA(intf, type, name) META_IMPL_ARRAY_PROPERTY_DATA_VALUE(intf, type, name, {})
258 
259 #define META_STATIC_ARRAY_PROPERTY_DATA(...)                                                 \
260     META_EXPAND(META_GET_MACRO5_IMPL(__VA_ARGS__, META_IMPL_ARRAY_PROPERTY_DATA_VALUE_FLAGS, \
261         META_IMPL_ARRAY_PROPERTY_DATA_VALUE, META_IMPL_ARRAY_PROPERTY_DATA)(__VA_ARGS__))
262 //---
263 
264 //--- Property forwarding
265 #define META_STATIC_FORWARDED_PROPERTY_DATA(intf, type, name)                                                  \
266     { META_NS::MetadataType::PROPERTY, intf::INTERFACE_INFO, #name,                                            \
267         [](const BASE_NS::shared_ptr<META_NS::IOwner>& owner, const META_NS::StaticMetadata&) {                \
268             auto i = interface_cast<intf>(owner);                                                              \
269             auto p = interface_pointer_cast<::CORE_NS::IInterface>(i ? i->Property##name() : nullptr);         \
270             return BASE_NS::shared_ptr<::CORE_NS::IInterface>(p, const_cast<::CORE_NS::IInterface*>(p.get())); \
271         },                                                                                                     \
272         [] { return META_NS::ConstructAnyHelper<type>({}); }, nullptr,                                         \
273         uint8_t(uint8_t(META_NS::Internal::StaticMetaFlag::FORWARD) |                                          \
274                 META_NS::GetPropertySMDFlags(&intf::Property##name, 0)) },
275 
276 #define META_STATIC_FORWARDED_ARRAY_PROPERTY_DATA(intf, type, name)                                            \
277     { META_NS::MetadataType::PROPERTY, intf::INTERFACE_INFO, #name,                                            \
278         [](const BASE_NS::shared_ptr<META_NS::IOwner>& owner, const META_NS::StaticMetadata&) {                \
279             auto i = interface_cast<intf>(owner);                                                              \
280             auto p = interface_pointer_cast<::CORE_NS::IInterface>(i ? i->Property##name() : nullptr);         \
281             return BASE_NS::shared_ptr<::CORE_NS::IInterface>(p, const_cast<::CORE_NS::IInterface*>(p.get())); \
282         },                                                                                                     \
283         [] { return META_NS::ConstructArrayAnyHelper<type>({}); }, nullptr,                                    \
284         uint8_t(uint8_t(META_NS::Internal::StaticMetaFlag::FORWARD) |                                          \
285                 META_NS::GetPropertySMDFlags(&intf::Property##name, 0)) },
286 //---
287 
288 #define META_STATIC_EVENT_DATA(intf, type, name) \
289     { META_NS::MetadataType::EVENT, intf::INTERFACE_INFO, #name, META_NS::CreateEventConstructor<type>(), nullptr },
290 
291 //--- Event forwarding
292 #define META_STATIC_FORWARDED_EVENT_DATA(intf, type, name)                                      \
293     { META_NS::MetadataType::EVENT, intf::INTERFACE_INFO, #name,                                \
294         [](const BASE_NS::shared_ptr<META_NS::IOwner>& owner, const META_NS::StaticMetadata&) { \
295             auto i = interface_cast<intf>(owner);                                               \
296             return interface_pointer_cast<::CORE_NS::IInterface>(                               \
297                 i ? i->Event##name(META_NS::MetadataQuery::CONSTRUCT_ON_REQUEST) : nullptr);    \
298         },                                                                                      \
299         nullptr, nullptr, uint8_t(META_NS::Internal::StaticMetaFlag::FORWARD) },
300 //---
301 
302 #define META_STATIC_FUNCTION_DATA(intf, func, ...)                                          \
303     { META_NS::MetadataType::FUNCTION, intf::INTERFACE_INFO, #func,                         \
304         META_NS::CreateFunctionConstructor<intf, &intf ::func>(), [] {                      \
305             ::BASE_NS::string_view arr[] = { "", __VA_ARGS__ };                             \
306             return META_NS::ConstructAny<META_NS::ICallContext::Ptr>(                       \
307                 META_NS::CreateCallContext(&intf ::func, ::META_NS::ParamNameToView(arr))); \
308         } },
309 
310 #define META_PRIVATE_PROPERTY_TYPED_IMPL(type, name)                                                               \
311     META_NS::Property<type> name() noexcept                                                                        \
312     {                                                                                                              \
313         return META_NS::Property<type> { this->GetProperty(#name, META_NS::MetadataQuery::CONSTRUCT_ON_REQUEST) }; \
314     }                                                                                                              \
315     META_NS::ConstProperty<type> name() const noexcept                                                             \
316     {                                                                                                              \
317         return META_NS::ConstProperty<type> { this->GetProperty(                                                   \
318             #name, META_NS::MetadataQuery::CONSTRUCT_ON_REQUEST) };                                                \
319     }
320 
321 #define META_PRIVATE_ARRAY_PROPERTY_TYPED_IMPL(type, name)            \
322     META_NS::ConstArrayProperty<type> name() const noexcept           \
323     {                                                                 \
324         return META_NS::ConstArrayProperty<type> { this->GetProperty( \
325             #name, META_NS::MetadataQuery::CONSTRUCT_ON_REQUEST) };   \
326     }                                                                 \
327     META_NS::ArrayProperty<type> name() noexcept                      \
328     {                                                                 \
329         return META_NS::ArrayProperty<type> { this->GetProperty(      \
330             #name, META_NS::MetadataQuery::CONSTRUCT_ON_REQUEST) };   \
331     }
332 
333 #define META_IMPLEMENT_READONLY_PROPERTY(type, name)                        \
334     ::META_NS::IProperty::ConstPtr Property##name() const noexcept override \
335     {                                                                       \
336         return this->GetProperty(#name);                                    \
337     }                                                                       \
338     META_PRIVATE_PROPERTY_TYPED_IMPL(::META_NS::PropertyType_v<type>, name)
339 
340 #define META_IMPLEMENT_CACHED_READONLY_PROPERTY(type, name)                                                 \
341     mutable META_NS::Property<::META_NS::PropertyType_v<type>> metaProperty##name##_;                       \
342     ::META_NS::IProperty::ConstPtr Property##name() const noexcept override                                 \
343     {                                                                                                       \
344         if (!metaProperty##name##_) {                                                                       \
345             metaProperty##name##_ = this->GetProperty(#name, META_NS::MetadataQuery::CONSTRUCT_ON_REQUEST); \
346         }                                                                                                   \
347         return metaProperty##name##_;                                                                       \
348     }                                                                                                       \
349     META_PRIVATE_PROPERTY_TYPED_IMPL(::META_NS::PropertyType_v<type>, name)
350 
351 #define META_IMPLEMENT_PROPERTY(type, name)                                                                   \
352     META_IMPLEMENT_READONLY_PROPERTY(type, name)                                                              \
353     ::META_NS::IProperty::Ptr Property##name() noexcept override                                              \
354     {                                                                                                         \
355         ::META_NS::IProperty::Ptr p = this->GetProperty(#name, META_NS::MetadataQuery::CONSTRUCT_ON_REQUEST); \
356         CORE_ASSERT_MSG(p, "Failed to get property '" #name "'");                                             \
357         return p;                                                                                             \
358     }
359 
360 #define META_IMPLEMENT_CACHED_PROPERTY(type, name)                                                          \
361     META_IMPLEMENT_CACHED_READONLY_PROPERTY(type, name)                                                     \
362     ::META_NS::IProperty::Ptr Property##name() noexcept override                                            \
363     {                                                                                                       \
364         if (!metaProperty##name##_) {                                                                       \
365             metaProperty##name##_ = this->GetProperty(#name, META_NS::MetadataQuery::CONSTRUCT_ON_REQUEST); \
366             CORE_ASSERT_MSG(metaProperty##name##_, "Failed to get property '" #name "'");                   \
367         }                                                                                                   \
368         return metaProperty##name##_;                                                                       \
369     }
370 
371 #define META_IMPLEMENT_READONLY_ARRAY_PROPERTY(type, name)                                                         \
372     ::META_NS::IProperty::ConstPtr Property##name() const noexcept override                                        \
373     {                                                                                                              \
374         ::META_NS::IProperty::ConstPtr p = this->GetProperty(#name, META_NS::MetadataQuery::CONSTRUCT_ON_REQUEST); \
375         CORE_ASSERT_MSG(p, "Failed to get property '" #name "'");                                                  \
376         return p;                                                                                                  \
377     }                                                                                                              \
378     META_PRIVATE_ARRAY_PROPERTY_TYPED_IMPL(type, name)
379 
380 #define META_IMPLEMENT_CACHED_READONLY_ARRAY_PROPERTY(type, name)                                           \
381     mutable META_NS::ArrayProperty<::META_NS::PropertyType_v<type>> metaProperty##name##_;                  \
382     ::META_NS::IProperty::ConstPtr Property##name() const noexcept override                                 \
383     {                                                                                                       \
384         if (!metaProperty##name##_) {                                                                       \
385             metaProperty##name##_ = this->GetProperty(#name, META_NS::MetadataQuery::CONSTRUCT_ON_REQUEST); \
386             CORE_ASSERT_MSG(metaProperty##name##_, "Failed to get property '" #name "'");                   \
387         }                                                                                                   \
388         return metaProperty##name##_;                                                                       \
389     }                                                                                                       \
390     META_PRIVATE_ARRAY_PROPERTY_TYPED_IMPL(type, name)
391 
392 #define META_IMPLEMENT_ARRAY_PROPERTY(type, name)                                                             \
393     META_IMPLEMENT_READONLY_ARRAY_PROPERTY(type, name)                                                        \
394     ::META_NS::IProperty::Ptr Property##name() noexcept override                                              \
395     {                                                                                                         \
396         ::META_NS::IProperty::Ptr p = this->GetProperty(#name, META_NS::MetadataQuery::CONSTRUCT_ON_REQUEST); \
397         CORE_ASSERT_MSG(p, "Failed to get property '" #name "'");                                             \
398         return p;                                                                                             \
399     }
400 
401 #define META_IMPLEMENT_CACHED_ARRAY_PROPERTY(type, name)                                                    \
402     META_IMPLEMENT_CACHED_READONLY_PROPERTY(type, name)                                                     \
403     ::META_NS::IProperty::Ptr Property##name() noexcept override                                            \
404     {                                                                                                       \
405         if (!metaProperty##name##_) {                                                                       \
406             metaProperty##name##_ = this->GetProperty(#name, META_NS::MetadataQuery::CONSTRUCT_ON_REQUEST); \
407             CORE_ASSERT_MSG(metaProperty##name##_, "Failed to get property '" #name "'");                   \
408         }                                                                                                   \
409         return metaProperty##name##_;                                                                       \
410     }
411 
412 /**
413  * @brief Make forwarding function for the read-only property.
414  */
415 #define META_FORWARD_READONLY_PROPERTY(type, name, forwarder)             \
416     META_NS::IProperty::ConstPtr Property##name() const noexcept override \
417     {                                                                     \
418         return forwarder;                                                 \
419     }                                                                     \
420     META_READONLY_PROPERTY_TYPED_IMPL(type, name)
421 
422 /**
423  * @brief Make forwarding function for the property.
424  */
425 #define META_FORWARD_PROPERTY(type, name, forwarder)           \
426     META_FORWARD_READONLY_PROPERTY(type, name, forwarder)      \
427     META_NS::IProperty::Ptr Property##name() noexcept override \
428     {                                                          \
429         return forwarder;                                      \
430     }                                                          \
431     META_PROPERTY_TYPED_IMPL(type, name)
432 
433 #define META_FORWARD_BASE_READONLY_PROPERTY(type, name) \
434     META_FORWARD_READONLY_PROPERTY(type, name, this->Super::Property##name())
435 
436 #define META_FORWARD_BASE_PROPERTY(type, name) META_FORWARD_PROPERTY(type, name, this->Super::Property##name())
437 
438 #define META_FORWARD_READONLY_ARRAY_PROPERTY(type, name, forwarder)       \
439     META_NS::IProperty::ConstPtr Property##name() const noexcept override \
440     {                                                                     \
441         return forwarder;                                                 \
442     }                                                                     \
443     META_READONLY_ARRAY_PROPERTY_TYPED_IMPL(type, name)
444 
445 /**
446  * @brief Make forwarding function for the property.
447  */
448 #define META_FORWARD_ARRAY_PROPERTY(type, name, forwarder)      \
449     META_FORWARD_READONLY_ARRAY_PROPERTY(type, name, forwarder) \
450     META_NS::IProperty::Ptr Property##name() noexcept override  \
451     {                                                           \
452         return forwarder;                                       \
453     }                                                           \
454     META_ARRAY_PROPERTY_TYPED_IMPL(type, name)
455 
456 #define META_FORWARD_BASE_READONLY_ARRAY_PROPERTY(type, name) \
457     META_FORWARD_READONLY_ARRAY_PROPERTY(type, name, this->Super::Property##name())
458 
459 #define META_FORWARD_BASE_ARRAY_PROPERTY(type, name) \
460     META_FORWARD_ARRAY_PROPERTY(type, name, this->Super::Property##name())
461 
462 #define META_IMPLEMENT_EVENT(type, name)                                                         \
463     BASE_NS::shared_ptr<::META_NS::IEvent> Event##name(META_NS::MetadataQuery q) const override  \
464     {                                                                                            \
465         BASE_NS::shared_ptr<const ::META_NS::IEvent> p = this->GetEvent(#name, q);               \
466         return BASE_NS::shared_ptr<::META_NS::IEvent>(p, const_cast<META_NS::IEvent*>(p.get())); \
467     }                                                                                            \
468     META_EVENT_TYPED_IMPL(type, name)
469 
470 #define META_FORWARD_EVENT(type, name, forwarder)                                               \
471     BASE_NS::shared_ptr<::META_NS::IEvent> Event##name(META_NS::MetadataQuery q) const override \
472     {                                                                                           \
473         return forwarder(q);                                                                    \
474     }                                                                                           \
475     META_EVENT_TYPED_IMPL(type, name)
476 
477 #define META_FORWARD_EVENT_CLASS(type, name, targetClass)                                       \
478     BASE_NS::shared_ptr<::META_NS::IEvent> Event##name(META_NS::MetadataQuery q) const override \
479     {                                                                                           \
480         return targetClass::Event##name(q);                                                     \
481     }                                                                                           \
482     ::META_NS::Event<type> name() const                                                         \
483     {                                                                                           \
484         return targetClass::Event##name(q);                                                     \
485     }
486 
487 #endif
488