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_METADATA_HELPERS_H
17 #define META_EXT_METADATA_HELPERS_H
18
19 #include <meta/interface/intf_metadata.h>
20 #include <meta/interface/intf_object.h>
21 #include <meta/interface/intf_owner.h>
22 #include <meta/interface/static_object_metadata.h>
23
META_BEGIN_NAMESPACE()24 META_BEGIN_NAMESPACE()
25
26 /// Get the aggregate baseclass' metadata
27 inline const StaticObjectMetadata* GetBaseClassMeta(const StaticObjectMetadata* d)
28 {
29 while (d && !d->aggregate) {
30 d = d->baseclass;
31 }
32 return d ? d->aggregate : nullptr;
33 }
34
35 /// Get the aggregate baseclass' metadata
GetBaseClassMeta(const IObject::ConstPtr & obj)36 inline const StaticObjectMetadata* GetBaseClassMeta(const IObject::ConstPtr& obj)
37 {
38 auto m = interface_cast<IStaticMetadata>(obj);
39 return m ? GetBaseClassMeta(m->GetStaticMetadata()) : nullptr;
40 }
41
42 /// Get the aggregate baseclass' object id
GetBaseClass(const IObject::ConstPtr & obj)43 inline ObjectId GetBaseClass(const IObject::ConstPtr& obj)
44 {
45 if (auto m = GetBaseClassMeta(obj)) {
46 if (m->classInfo) {
47 return m->classInfo->Id();
48 }
49 }
50 return {};
51 }
52
53 /// Search static metadata in class metadata, not considering aggregate bases
FindStaticMetadataInClass(const StaticObjectMetadata & data,BASE_NS::string_view name,MetadataType type)54 inline const StaticMetadata* FindStaticMetadataInClass(
55 const StaticObjectMetadata& data, BASE_NS::string_view name, MetadataType type)
56 {
57 for (size_t i = 0; i != data.size; ++i) {
58 auto& p = data.metadata[i];
59 if (p.name == name && ((uint8_t(p.type) & uint8_t(type)) || type == MetadataType::UNKNOWN)) {
60 return &p;
61 }
62 }
63 return data.baseclass ? FindStaticMetadataInClass(*data.baseclass, name, type) : nullptr;
64 }
65
66 /**
67 * @brief Find static metadata for given name and type
68 * @param data Metadata to search from
69 * @param name Name of the entity to search metadata for
70 * @param type Type of the entity to search, this contains bit field of the possible types
71 * @notice Returns the first matching metadata
72 * @return Static metadata for matching entity.
73 */
FindStaticMetadata(const StaticObjectMetadata & data,BASE_NS::string_view name,MetadataType type)74 inline const StaticMetadata* FindStaticMetadata(
75 const StaticObjectMetadata& data, BASE_NS::string_view name, MetadataType type)
76 {
77 if (auto ret = FindStaticMetadataInClass(data, name, type)) {
78 return ret;
79 }
80 auto base = GetBaseClassMeta(&data);
81 return base ? FindStaticMetadata(*base, name, type) : nullptr;
82 }
83
84 template<typename Interface>
85 struct MetadataObject {
86 typename Interface::Ptr object {};
87 bool isForward {};
88 };
89
90 /// Construct entity from given metadata
91 template<typename Interface>
ConstructFromMetadata(const IOwner::Ptr & self,const StaticMetadata & pm)92 MetadataObject<Interface> ConstructFromMetadata(const IOwner::Ptr& self, const StaticMetadata& pm)
93 {
94 auto res = pm.create(self, pm);
95 if (!res) {
96 CORE_LOG_W("Failed to create entity from static metadata [name=%s]", pm.name);
97 }
98 return MetadataObject<Interface> { interface_pointer_cast<Interface>(res),
99 bool(pm.flags & uint8_t(Internal::StaticMetaFlag::FORWARD)) };
100 }
101
102 /// Find and construct entity with given criteria starting search from static metadata
103 template<typename Interface>
ConstructFromMetadata(const IOwner::Ptr & self,const StaticObjectMetadata & sm,BASE_NS::string_view name,MetadataType type)104 MetadataObject<Interface> ConstructFromMetadata(
105 const IOwner::Ptr& self, const StaticObjectMetadata& sm, BASE_NS::string_view name, MetadataType type)
106 {
107 if (auto pm = FindStaticMetadata(sm, name, type)) {
108 return ConstructFromMetadata<Interface>(self, *pm);
109 }
110 return {};
111 }
112
113 /// Find and construct entity with given criteria for object
114 template<typename Interface>
ConstructFromMetadata(const IOwner::Ptr & self,BASE_NS::string_view name,MetadataType type)115 MetadataObject<Interface> ConstructFromMetadata(const IOwner::Ptr& self, BASE_NS::string_view name, MetadataType type)
116 {
117 if (auto s = interface_cast<IStaticMetadata>(self)) {
118 if (auto pm = s->GetStaticMetadata()) {
119 return ConstructFromMetadata<Interface>(self, *pm, name, type);
120 }
121 }
122 return {};
123 }
124
GetMetaPropertyType(const StaticMetadata & m)125 inline TypeId GetMetaPropertyType(const StaticMetadata& m)
126 {
127 if (m.type == MetadataType::PROPERTY && m.runtimeValue) {
128 if (auto def = m.runtimeValue()) {
129 return def->GetTypeId();
130 }
131 }
132 return {};
133 }
134
135 /// Get all static metadata recursively without considering aggregate bases
GetAllStaticMetadataInClass(const StaticObjectMetadata & data,MetadataType type)136 inline BASE_NS::vector<MetadataInfo> GetAllStaticMetadataInClass(const StaticObjectMetadata& data, MetadataType type)
137 {
138 BASE_NS::vector<MetadataInfo> result;
139 for (size_t i = 0; i != data.size; ++i) {
140 auto& p = data.metadata[i];
141 if (uint8_t(p.type) & uint8_t(type)) {
142 MetadataInfo info { p.type, p.name, p.interfaceInfo };
143 if (p.type == MetadataType::PROPERTY) {
144 info.propertyType = GetMetaPropertyType(p);
145 info.readOnly = p.flags & static_cast<uint8_t>(Internal::PropertyFlag::READONLY);
146 }
147 info.data = &p;
148 result.push_back(info);
149 }
150 }
151 if (data.baseclass) {
152 auto r = GetAllStaticMetadataInClass(*data.baseclass, type);
153 result.insert(result.end(), r.begin(), r.end());
154 }
155 return result;
156 }
157
158 /// Get all static metadata recursively
GetAllStaticMetadata(const StaticObjectMetadata & data,MetadataType type)159 inline BASE_NS::vector<MetadataInfo> GetAllStaticMetadata(const StaticObjectMetadata& data, MetadataType type)
160 {
161 auto result = GetAllStaticMetadataInClass(data, type);
162 if (auto base = GetBaseClassMeta(&data)) {
163 auto r = GetAllStaticMetadata(*base, type);
164 result.insert(result.end(), r.begin(), r.end());
165 }
166 return result;
167 }
168
169 META_END_NAMESPACE()
170
171 #endif
172