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 #ifndef META_BASE_META_TYPES_H
16 #define META_BASE_META_TYPES_H
17
18 #include <stdint.h>
19
20 #include <base/namespace.h>
21 #include <base/util/compile_time_hashes.h>
22 #include <base/util/uid.h>
23 #include <core/property/property_types.h>
24
25 #include <meta/base/type_traits.h>
26
27 META_BEGIN_NAMESPACE()
28
29 template<typename t>
30 struct MetaType;
31
32 template<class T, class B>
CorePropertyTypeDeclFromType()33 inline constexpr auto CorePropertyTypeDeclFromType()
34 {
35 if constexpr (CORE_NS::PropertySystem::is_defined<T>().value) {
36 return CORE_NS::PropertySystem::PropertyTypeDeclFromType<T, B>();
37 }
38 return CORE_NS::PropertyTypeDecl {};
39 }
40
MakeUidImpl(uint64_t hash,const char (& type)[9])41 inline constexpr BASE_NS::Uid MakeUidImpl(uint64_t hash, const char (&type)[9])
42 {
43 uint8_t data[16u] { static_cast<uint8_t>((hash >> 56) & 0xFF), static_cast<uint8_t>((hash >> 48) & 0xFF),
44 static_cast<uint8_t>((hash >> 40) & 0xFF), static_cast<uint8_t>((hash >> 32) & 0xFF),
45 static_cast<uint8_t>((hash >> 24) & 0xFF), static_cast<uint8_t>((hash >> 16) & 0xFF),
46 static_cast<uint8_t>((hash >> 8) & 0xFF), static_cast<uint8_t>(hash & 0xFF), static_cast<uint8_t>(type[0]),
47 static_cast<uint8_t>(type[1]), static_cast<uint8_t>(type[2]), static_cast<uint8_t>(type[3]),
48 static_cast<uint8_t>(type[4]), static_cast<uint8_t>(type[5]), static_cast<uint8_t>(type[6]),
49 static_cast<uint8_t>(type[7]) };
50 return BASE_NS::Uid(data);
51 }
52
53 /**
54 * @brief Generate UID from name and type string.
55 */
MakeUid(const char * const name,const char (& type)[9])56 inline constexpr BASE_NS::Uid MakeUid(const char* const name, const char (&type)[9])
57 {
58 return MakeUidImpl(BASE_NS::CompileTime::FNV1aHash(name), type);
59 }
60
61 template<typename Type>
62 using EnableIfDefined = decltype(sizeof(Type));
63
64 template<typename Type>
65 constexpr bool IsDefined_v = META_NS::IsDetected_v<EnableIfDefined, Type>; // NOLINT(readability-identifier-naming)
66
67 template<typename Type>
68 constexpr bool HasUid_v = IsDefined_v<MetaType<Type>>; // NOLINT(readability-identifier-naming)
69
70 /**
71 * @brief Generate UID from registered type and type string.
72 */
73 template<typename Type>
MakeUid(const char (& type)[9])74 inline constexpr BASE_NS::Uid MakeUid(const char (&type)[9])
75 {
76 static_assert(HasUid_v<Type>, "META_TYPE missing for given type");
77 return MakeUidImpl(BASE_NS::CompileTime::FNV1aHash(MetaType<Type>::name), type);
78 }
79
80 template<typename Type>
CombineHash(uint64_t hash)81 inline constexpr uint64_t CombineHash(uint64_t hash)
82 {
83 static_assert(HasUid_v<Type>, "META_TYPE missing for given type");
84
85 return hash ^
86 // 12: shift 4: shift
87 (BASE_NS::CompileTime::FNV1aHash(MetaType<Type>::name) + 0x9e3779b97f4a7c15LLU + (hash << 12) + (hash >> 4));
88 }
89
90 /**
91 * @brief Generate UID from multiple registered types and type string.
92 */
93 template<typename... Types>
MakeUidFromTypes(const char (& type)[9])94 inline constexpr BASE_NS::Uid MakeUidFromTypes(const char (&type)[9])
95 {
96 uint64_t hash {};
97 if constexpr (sizeof...(Types) != 0) {
98 hash = (CombineHash<Types>(hash), ...);
99 }
100 return MakeUidImpl(hash, type);
101 }
102
103 /**
104 * @brief Check if UID is valid.
105 */
IsValidUid(const BASE_NS::Uid & uid)106 inline constexpr bool IsValidUid(const BASE_NS::Uid& uid)
107 {
108 return uid.data[0] && uid.data[1];
109 }
110
111 /**
112 * @brief Generate UID for read-only property type.
113 */
114 template<typename Type>
UidFromReadOnlyType()115 inline constexpr BASE_NS::Uid UidFromReadOnlyType()
116 {
117 // At least visual c++ 2017 has a bug that causes this uid variable to be uninitialised at runtime and so crashing
118 // We know at least visual c++ 2022 works...
119 #if defined(_MSC_VER) && _MSC_VER < 1930
120 return MakeUid<Type>("ReadOnly");
121 #else
122 constexpr auto uid = MakeUid<Type>("ReadOnly");
123 static_assert(IsValidUid(uid));
124 return uid;
125 #endif
126 }
127 /**
128 * @brief Generate UID for property type.
129 */
130
131 template<typename Type>
UidFromType()132 inline constexpr BASE_NS::Uid UidFromType()
133 {
134 // At least visual c++ 2017 has a bug that causes this uid variable to be uninitialised at runtime and so crashing
135 // We know at least visual c++ 2022 works...
136 #if defined(_MSC_VER) && _MSC_VER < 1930
137 return MakeUid<Type>("Property");
138 #else
139 constexpr auto uid = MakeUid<Type>("Property");
140 static_assert(IsValidUid(uid));
141 return uid;
142 #endif
143 }
144
145 template<typename Type>
ArrayUidFromType()146 inline constexpr BASE_NS::Uid ArrayUidFromType()
147 {
148 if constexpr (BASE_NS::is_array_v<Type>) {
149 return UidFromType<Type>();
150 }
151 return UidFromType<Type[]>();
152 }
153
154 template<typename Type>
ItemUidFromType()155 inline constexpr BASE_NS::Uid ItemUidFromType()
156 {
157 return UidFromType<BASE_NS::remove_extent_t<Type>>();
158 }
159
160 template<>
161 struct MetaType<void> {
162 // NOLINTBEGIN(readability-identifier-naming)
163 static constexpr char name[] = "void";
164 static constexpr CORE_NS::PropertyTypeDecl coreType = CorePropertyTypeDeclFromType<void, BASE_NS::false_type>();
165 // NOLINTEND(readability-identifier-naming)
166 };
167
168 META_END_NAMESPACE()
169
170 /**
171 * @brief To introduce new types to the property system, call META_TYPE(<type>) in global namespace.
172 */
173 #define META_TYPE_IMPL(a, n) \
174 template<> \
175 struct ::META_NS::MetaType<a> { \
176 static constexpr char name[] = n; \
177 static constexpr CORE_NS::PropertyTypeDecl coreType = \
178 ::META_NS::CorePropertyTypeDeclFromType<a, BASE_NS::false_type>(); \
179 }; \
180 template<> \
181 struct ::META_NS::MetaType<a[]> { \
182 static constexpr char name[] = n "[]"; \
183 static constexpr CORE_NS::PropertyTypeDecl coreType = \
184 ::META_NS::CorePropertyTypeDeclFromType<a, BASE_NS::true_type>(); \
185 }; \
186 template<> \
187 struct ::META_NS::MetaType<BASE_NS::vector<a>> { \
188 static constexpr char name[] = "BASE_NS::vector<" n ">"; \
189 static constexpr CORE_NS::PropertyTypeDecl coreType = \
190 ::META_NS::CorePropertyTypeDeclFromType<BASE_NS::vector<a>, BASE_NS::false_type>(); \
191 };
192
193 #define META_TYPE(a) META_TYPE_IMPL(a, #a)
194 #define META_INTERFACE_TYPE(a) \
195 META_TYPE_IMPL(a::Ptr, #a "::Ptr") \
196 META_TYPE_IMPL(a::ConstPtr, #a "::ConstPtr") \
197 META_TYPE_IMPL(a::WeakPtr, #a "::WeakPtr") \
198 META_TYPE_IMPL(a::ConstWeakPtr, #a "::ConstWeakPtr")
199
200 META_TYPE(char);
201 META_TYPE(wchar_t);
202 META_TYPE(float);
203 META_TYPE(double);
204 META_TYPE(bool);
205 META_TYPE(uint8_t);
206 META_TYPE(uint16_t);
207 META_TYPE(uint32_t);
208 META_TYPE(uint64_t);
209 META_TYPE(int8_t);
210 META_TYPE(int16_t);
211 META_TYPE(int32_t);
212 META_TYPE(int64_t);
213 #ifdef __APPLE__
214 META_TYPE(size_t);
215 #endif
216 META_TYPE(BASE_NS::Uid);
217 META_TYPE(BASE_NS::string);
218 META_TYPE(BASE_NS::string_view);
219 META_TYPE(BASE_NS::Math::Vec2);
220 META_TYPE(BASE_NS::Math::UVec2);
221 META_TYPE(BASE_NS::Math::IVec2);
222 META_TYPE(BASE_NS::Math::Vec3);
223 META_TYPE(BASE_NS::Math::UVec3);
224 META_TYPE(BASE_NS::Math::IVec3);
225 META_TYPE(BASE_NS::Math::Vec4);
226 META_TYPE(BASE_NS::Math::UVec4);
227 META_TYPE(BASE_NS::Math::IVec4);
228 META_TYPE(BASE_NS::Math::Quat);
229 META_TYPE(BASE_NS::Math::Mat3X3);
230 META_TYPE(BASE_NS::Math::Mat4X4);
231 META_TYPE(CORE_NS::Entity);
232 META_TYPE(CORE_NS::EntityReference);
233
234 CORE_BEGIN_NAMESPACE()
235 class IPropertyHandle;
236 DECLARE_PROPERTY_TYPE(CORE_NS::IPropertyHandle*);
237 CORE_END_NAMESPACE()
238
239 META_TYPE(CORE_NS::IPropertyHandle*);
240
241 #endif
242