/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef META_EXT_IMPLEMENTATION_MACROS_H
#define META_EXT_IMPLEMENTATION_MACROS_H
#include
#include
#include
#include
#include
#include
#include
/**
* @brief Access property variable introduced with META_IMPLEMENT_*_PROPERTY
*/
#define META_ACCESS_PROPERTY(name) metaProperty##name##_
#define META_ACCESS_PROPERTY_VALUE(name) metaProperty##name##_->GetValue()
/**
* @brief Access event variable introduced with META_IMPLEMENT_*_EVENT
*/
#define META_ACCESS_EVENT(name) metaEvent##name##_
#define META_VALUE_PTR(interface, classId) ::META_NS::ValuePtrImpl::Instance
META_BEGIN_NAMESPACE()
constexpr ObjectFlagBitsValue DEFAULT_PROPERTY_FLAGS = ObjectFlagBitsValue { ObjectFlagBits::SERIALIZE };
constexpr ObjectFlagBitsValue DEFAULT_PROPERTY_FLAGS_NO_SER = ObjectFlagBitsValue { ObjectFlagBits::NONE };
META_END_NAMESPACE()
#define META_DEFINE_PROPERTY_VAR(intf, name, type, defaultValue, flags) \
::META_NS::Property<::META_NS::PropertyType_v> metaProperty##name##_ = \
this->template RegisterStaticPropertyMetadata<::META_NS::PropertyType_v>( \
intf, #name, flags, \
[] { return ::META_NS::IProperty::Ptr(::META_NS::ConstructProperty(#name, defaultValue, flags)); }, \
[](auto me) { /*workaround for older msvc not supporting decltype(this) without capture*/ \
return [](void* self, const ::META_NS::IProperty::Ptr& p) { \
if (p) { \
static_cast(self)->metaProperty##name##_ = p; \
} \
return p != nullptr; \
}; \
}(this));
#define META_DEFINE_PROPERTY_VARArray(intf, name, type, defaultValue, flags) \
::META_NS::ArrayProperty metaProperty##name##_ = this->template RegisterStaticPropertyMetadata( \
intf, #name, flags, \
[] { return ::META_NS::IProperty::Ptr(::META_NS::ConstructArrayProperty(#name, defaultValue, flags)); }, \
[](auto me) { /*workaround for older msvc not supporting decltype(this) without capture*/ \
return [](void* self, const ::META_NS::IProperty::Ptr& p) { \
if (p) { \
static_cast(self)->metaProperty##name##_ = p; \
} \
return p != nullptr; \
}; \
}(this));
#define META_DEFINE_READONLY_PROPERTY(propType, intf, name, type, defaultValue, flags) \
META_DEFINE_PROPERTY_VAR##propType( \
intf, name, type, defaultValue, flags)::META_NS::IProperty::ConstPtr Property##name() const noexcept override \
{ \
return metaProperty##name##_; \
} \
META_READONLY_PROPERTY_TYPED_IMPL(::META_NS::PropertyType_v, name)
#define META_DEFINE_PROPERTY(propType, intf, name, type, defaultValue, flags) \
META_DEFINE_READONLY_PROPERTY(propType, intf, name, type, defaultValue, flags) \
::META_NS::IProperty::Ptr Property##name() noexcept override \
{ \
return metaProperty##name##_; \
} \
META_PROPERTY_TYPED_IMPL(::META_NS::PropertyType_v, name)
#define META_DEFINE_READONLY_ARRAY_PROPERTY(propType, intf, name, type, defaultValue, flags) \
META_DEFINE_PROPERTY_VAR##propType( \
intf, name, type, defaultValue, flags)::META_NS::IProperty::ConstPtr Property##name() const noexcept override \
{ \
return metaProperty##name##_; \
} \
META_READONLY_ARRAY_PROPERTY_TYPED_IMPL(type, name)
#define META_DEFINE_ARRAY_PROPERTY(propType, intf, name, type, defaultValue, flags) \
META_DEFINE_READONLY_ARRAY_PROPERTY(propType, intf, name, type, defaultValue, flags) \
::META_NS::IProperty::Ptr Property##name() noexcept override \
{ \
return metaProperty##name##_; \
} \
META_ARRAY_PROPERTY_TYPED_IMPL(type, name)
#define META_GET_PROPERTY4(macro, propType, intf, type, name, defaultValue, flags) \
macro(propType, intf, name, type, defaultValue, \
::META_NS::ObjectFlagBitsValue { flags } | ::META_NS::ObjectFlagBits::NATIVE)
#define META_GET_PROPERTY3(macro, propType, intf, type, name, defaultValue) \
macro(propType, intf, name, type, defaultValue, \
::META_NS::DEFAULT_PROPERTY_FLAGS | ::META_NS::ObjectFlagBits::NATIVE)
#define META_GET_PROPERTY2(macro, propType, intf, type, name) \
macro(propType, intf, name, type, {}, ::META_NS::DEFAULT_PROPERTY_FLAGS | ::META_NS::ObjectFlagBits::NATIVE)
#define META_GET_PROPERTY(macro, propType, ...) \
META_EXPAND(META_GET_MACRO5_IMPL(__VA_ARGS__, META_GET_PROPERTY4, META_GET_PROPERTY3, META_GET_PROPERTY2)( \
macro, propType, __VA_ARGS__))
/**
* @brief Implement property that was introduced using META_PROPERTY in interface.
* This will add the property to static metadata and generates code to construct
* it when the object is constructed.
*/
#define META_IMPLEMENT_PROPERTY(...) \
META_EXPAND(META_GET_PROPERTY(META_DEFINE_PROPERTY,, META_NS::InterfaceInfo {}, __VA_ARGS__))
#define META_IMPLEMENT_READONLY_PROPERTY(...) \
META_EXPAND(META_GET_PROPERTY(META_DEFINE_READONLY_PROPERTY,, META_NS::InterfaceInfo {}, __VA_ARGS__))
#define META_IMPLEMENT_ARRAY_PROPERTY(...) \
META_EXPAND(META_GET_PROPERTY(META_DEFINE_ARRAY_PROPERTY, Array, META_NS::InterfaceInfo {}, __VA_ARGS__))
#define META_IMPLEMENT_READONLY_ARRAY_PROPERTY(...) \
META_EXPAND(META_GET_PROPERTY(META_DEFINE_READONLY_ARRAY_PROPERTY, Array, META_NS::InterfaceInfo {}, __VA_ARGS__))
/**
* @brief Same as META_IMPLEMENT_PROPERTY but first parameter tells which interface introduced this property.
*/
#define META_IMPLEMENT_INTERFACE_PROPERTY(intf, ...) \
META_EXPAND(META_GET_PROPERTY(META_DEFINE_PROPERTY,, intf::INTERFACE_INFO, __VA_ARGS__))
#define META_IMPLEMENT_INTERFACE_READONLY_PROPERTY(intf, ...) \
META_EXPAND(META_GET_PROPERTY(META_DEFINE_READONLY_PROPERTY,, intf::INTERFACE_INFO, __VA_ARGS__))
#define META_IMPLEMENT_INTERFACE_ARRAY_PROPERTY(intf, ...) \
META_EXPAND(META_GET_PROPERTY(META_DEFINE_ARRAY_PROPERTY, Array, intf::INTERFACE_INFO, __VA_ARGS__))
#define META_IMPLEMENT_INTERFACE_READONLY_ARRAY_PROPERTY(intf, ...) \
META_EXPAND(META_GET_PROPERTY(META_DEFINE_READONLY_ARRAY_PROPERTY, Array, intf::INTERFACE_INFO, __VA_ARGS__))
/**
* @brief Make forwarding function for the read-only property.
*/
#define META_FORWARD_READONLY_PROPERTY(type, name, forwarder) \
META_NS::IProperty::ConstPtr Property##name() const noexcept override \
{ \
return forwarder; \
} \
META_READONLY_PROPERTY_TYPED_IMPL(type, name)
/**
* @brief Make forwarding function for the property.
*/
#define META_FORWARD_PROPERTY(type, name, forwarder) \
META_FORWARD_READONLY_PROPERTY(type, name, forwarder) \
META_NS::IProperty::Ptr Property##name() noexcept override \
{ \
return forwarder; \
} \
META_PROPERTY_TYPED_IMPL(type, name)
#define META_FORWARD_BASE_READONLY_PROPERTY(type, name) \
META_FORWARD_READONLY_PROPERTY(type, name, this->Super::Property##name())
#define META_FORWARD_BASE_PROPERTY(type, name) META_FORWARD_PROPERTY(type, name, this->Super::Property##name())
#define META_FORWARD_READONLY_ARRAY_PROPERTY(type, name, forwarder) \
META_NS::IProperty::ConstPtr Property##name() const noexcept override \
{ \
return forwarder; \
} \
META_READONLY_ARRAY_PROPERTY_TYPED_IMPL(type, name)
/**
* @brief Make forwarding function for the property.
*/
#define META_FORWARD_ARRAY_PROPERTY(type, name, forwarder) \
META_FORWARD_READONLY_ARRAY_PROPERTY(type, name, forwarder) \
META_NS::IProperty::Ptr Property##name() noexcept override \
{ \
return forwarder; \
} \
META_ARRAY_PROPERTY_TYPED_IMPL(type, name)
#define META_FORWARD_BASE_READONLY_ARRAY_PROPERTY(type, name) \
META_FORWARD_READONLY_ARRAY_PROPERTY(type, name, this->Super::Property##name())
#define META_FORWARD_BASE_ARRAY_PROPERTY(type, name) \
META_FORWARD_ARRAY_PROPERTY(type, name, this->Super::Property##name())
#define META_DEFINE_EVENT_VAR(intf, type, name) \
mutable BASE_NS::shared_ptr<::META_NS::EventImpl> metaEvent##name##_ = \
this->template RegisterStaticEventMetadata( \
intf, #name, [] { return ::META_NS::IEvent::Ptr(CreateShared<::META_NS::EventImpl>(#name)); }, \
[](auto me) { /*workaround for older msvc not supporting decltype(this) without capture*/ \
return [](void* self, const ::META_NS::IEvent::Ptr& p) { \
if (p->GetCallableUid() == type::UID) { \
/* notice this is dangerous if same UID used for many different event types*/ \
static_cast(self)->metaEvent##name##_ = \
static_pointer_cast<::META_NS::EventImpl>(p); \
return true; \
} \
return false; \
}; \
}(this));
#define META_DEFINE_EVENT(intf, itype, etype, name) \
META_DEFINE_EVENT_VAR(intf, etype, name) \
BASE_NS::shared_ptr<::META_NS::IEvent> Event##name() const override \
{ \
CORE_ASSERT_MSG(metaEvent##name##_, "Metadata not initialized"); \
return metaEvent##name##_; \
} \
META_EVENT_TYPED_IMPL(itype, name)
#define META_GET_EVENT3(intf, itype, etype, name) META_DEFINE_EVENT(intf, itype, etype, name)
#define META_GET_EVENT2(intf, etype, name) META_DEFINE_EVENT(intf, etype, etype, name)
#define META_GET_EVENT(...) \
META_EXPAND(META_GET_MACRO4_IMPL(__VA_ARGS__, META_GET_EVENT3, META_GET_EVENT2)(__VA_ARGS__))
/**
* @brief Implement event that was introduced using META_PROPERTY in interface.
* This will add the event to static metadata and generates code to construct
* it when the object is constructed.
*/
#define META_IMPLEMENT_EVENT(...) META_EXPAND(META_GET_EVENT(META_NS::InterfaceInfo {}, __VA_ARGS__))
/**
* @brief Same as META_IMPLEMENT_EVENT but first parameter tells which interface introduced this event.
*/
#define META_IMPLEMENT_INTERFACE_EVENT(intf, ...) META_EXPAND(META_GET_EVENT(intf::INTERFACE_INFO, __VA_ARGS__))
#define META_FORWARD_EVENT(type, name, forwarder) \
BASE_NS::shared_ptr<::META_NS::IEvent> Event##name() const override \
{ \
return forwarder; \
} \
META_EVENT_TYPED_IMPL(type, name)
#define META_FORWARD_EVENT_CLASS(type, name, targetClass) \
BASE_NS::shared_ptr<::META_NS::IEvent> Event##name() const override \
{ \
return targetClass::Event##name(); \
} \
::META_NS::Event name() const \
{ \
return targetClass::Event##name(); \
}
#define META_DEFINE_FUNCTION_VAR(intf, class, func, ...) \
mutable ::META_NS::IFunction::Ptr metaFunc##func##_ = this->RegisterStaticFunctionMetadata( \
intf, #func, \
[](auto me) { \
return [](void* self) { \
auto ccontext = []() { \
::BASE_NS::string_view arr[] = { "", __VA_ARGS__ }; \
return CreateCallContext(&class ::func, ::META_NS::ParamNameToView(arr)); \
}; \
return ::META_NS::IFunction::Ptr(::META_NS::CreateFunction( \
#func, static_cast(self), &class ::func##MetaImpl, ccontext)); \
}; \
}(this), \
[]() { \
/*cannot have zero size array, so we add something in front and ParamNameToView removes it*/ \
BASE_NS::string_view arr[] = { "", __VA_ARGS__ }; \
return ::META_NS::CreateCallContext(&class ::func, ::META_NS::ParamNameToView(arr)); \
});
#define META_DEFINE_IMPL_FUNCTION(class, func) \
void func##MetaImpl(const ::META_NS::ICallContext::Ptr& context) \
{ \
::META_NS::CallFunction(context, this, &class ::func); \
}
#define META_IMPLEMENT_PLAIN_FUNCTION(class, func, ...) \
META_DEFINE_FUNCTION_VAR(META_NS::InterfaceInfo {}, class, func, __VA_ARGS__)
#define META_IMPLEMENT_FUNCTION(class, func, ...) \
META_IMPLEMENT_PLAIN_FUNCTION(class, func, __VA_ARGS__) \
META_DEFINE_IMPL_FUNCTION(class, func)
#define META_IMPLEMENT_INTERFACE_PLAIN_FUNCTION(interface, class, func, ...) \
META_DEFINE_FUNCTION_VAR(interface::INTERFACE_INFO, class, func, __VA_ARGS__)
#define META_IMPLEMENT_INTERFACE_FUNCTION(interface, class, func, ...) \
META_IMPLEMENT_INTERFACE_PLAIN_FUNCTION(interface, class, func, __VA_ARGS__) \
META_DEFINE_IMPL_FUNCTION(class, func)
#endif