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_BASE_TYPES_H
17 #define META_BASE_TYPES_H
18 
19 #include <base/containers/string_view.h>
20 #include <base/util/uid.h>
21 
22 #include <meta/base/ids.h>
23 #include <meta/base/namespace.h>
24 
25 #include "macros.h"
26 
27 META_BEGIN_NAMESPACE()
28 
29 using nullptr_t = decltype(nullptr);
30 
31 struct NoCheckT {};
32 constexpr NoCheckT NOCHECK;
33 
34 /**
35  * @brief The InterfaceInfo struct is used to register a new interface to the toolkit.
36  *        Call META_REGISTER_INTERFACE(<InterfaceName>, <InterfaceId>) to register the interface.
37  */
38 struct InterfaceInfo {
39     /** Returns the unique id of the interface. */
IdInterfaceInfo40     constexpr const TypeId& Id() const noexcept
41     {
42         return id;
43     }
44     /** Returns the name of the interface. */
NameInterfaceInfo45     constexpr const BASE_NS::string_view& Name() const noexcept
46     {
47         return name;
48     }
49     /** Returns the readable name of the interface. */
ReadableNameInterfaceInfo50     constexpr const BASE_NS::string_view& ReadableName() const noexcept
51     {
52         return readableName;
53     }
TypeIdInterfaceInfo54     constexpr operator TypeId() const noexcept
55     {
56         return id;
57     }
58     /** Implicit conversion operator InterfaceInfo->Uid. */
UidInterfaceInfo59     constexpr operator BASE_NS::Uid() const noexcept
60     {
61         return id.ToUid();
62     }
IsValidInterfaceInfo63     constexpr bool IsValid() const noexcept
64     {
65         return id.IsValid();
66     }
67     /** The Uid of the interface. Must be unique. */
68     TypeId id;
69     /** The name of the interface. */
70     BASE_NS::string_view name;
71     /** The readable name of the interface. */
72     BASE_NS::string_view readableName;
73 };
74 
75 inline bool operator==(const InterfaceInfo& lhs, const InterfaceInfo& rhs) noexcept
76 {
77     return lhs.id == rhs.id;
78 }
79 
80 inline bool operator!=(const InterfaceInfo& lhs, const InterfaceInfo& rhs) noexcept
81 {
82     return lhs.id != rhs.id;
83 }
84 
85 inline bool operator<(const InterfaceInfo& lhs, const InterfaceInfo& rhs) noexcept
86 {
87     return lhs.id < rhs.id;
88 }
89 
90 /**
91  * @brief List of supported object categories.
92  */
93 namespace ObjectCategory {
94 enum Bits : uint64_t {
95     /** Bitmask indicating any category except DEPRECATED */
96     ANY = 0,
97     /** The object does not belong to any specific category */
98     NO_CATEGORY = 0x1,
99     /** The object is a UI control */
100     WIDGET = 0x2,
101     /** The object is an animation */
102     ANIMATION = 0x4,
103     /** The object is a layout object */
104     LAYOUT = 0x8,
105     /** The object is a container object */
106     CONTAINER = 0x10,
107     /** The object is a curve */
108     CURVE = 0x20,
109     /** The object is a shape */
110     SHAPE = 0x40,
111     /** The object is for implementation */
112     INTERNAL = 0x80,
113     /** The object is an application-specific object. Objects registered by
114         applications should usually use this category. */
115     APPLICATION = 0x100,
116     /** The object is an animation modifier */
117     ANIMATION_MODIFIER = 0x200,
118     /** The object is a gesture */
119     GESTURE = 0x400,
120     /** The object is deprecated */
121     DEPRECATED = 0x800,
122 };
123 }
124 
125 using ObjectCategoryBits = ObjectCategory::Bits;
126 
127 /**
128  * @brief The ClassInfo struct contains the basic type information for a given class.
129  */
130 struct ClassInfo {
131     /** Returns the unique id of the class. */
IdClassInfo132     constexpr const ObjectId& Id() const noexcept
133     {
134         return id;
135     }
136     /** Returns the name of the class. */
NameClassInfo137     constexpr const BASE_NS::string_view& Name() const noexcept
138     {
139         return name;
140     }
141     /** Returns the readable name of the class. */
ReadableNameClassInfo142     constexpr const BASE_NS::string_view& ReadableName() const noexcept
143     {
144         return readableName;
145     }
146     /** Should the class be created as singleton? */
IsSingletonClassInfo147     constexpr bool IsSingleton() const noexcept
148     {
149         return singleton;
150     }
151     /** Implicit conversion operator ClassInfo->Uid. */
ObjectIdClassInfo152     constexpr operator ObjectId() const noexcept
153     {
154         return id;
155     }
156     /** The Uid of the class. Must be unique. */
157     ObjectId id;
158     /** The name of the class. */
159     BASE_NS::string_view name;
160     /** Category of the class */
161     ObjectCategoryBits category;
162     /** A flag indicating if the class can be created as singleton. */
163     bool singleton;
164     /** The readable name of the class. */
165     BASE_NS::string_view readableName;
166 };
167 
168 inline bool operator==(const ClassInfo& lhs, const ClassInfo& rhs) noexcept
169 {
170     return lhs.id == rhs.id;
171 }
172 
173 inline bool operator!=(const ClassInfo& lhs, const ClassInfo& rhs) noexcept
174 {
175     return lhs.id != rhs.id;
176 }
177 
178 inline bool operator<(const ClassInfo& lhs, const ClassInfo& rhs) noexcept
179 {
180     return lhs.id < rhs.id;
181 }
182 
183 /**
184  * @brief Register UID and category for class name. This tells there exists a concrete object type with this UID which
185  * can be constructed via ObjectRegistry. Example: META_REGISTER_CLASS(AnimationController,
186  * "32ccf293-e684-46e3-b733-85f9bbcc703c", ObjectCategoryBits::NO_CATEGORY)
187  */
188 #define META_REGISTER_IMPL_CLASS4(singleton, name, id, cat, readable)                                                  \
189     namespace ClassId {                                                                                                \
190     [[maybe_unused]] inline constexpr ::META_NS::ClassInfo name { BASE_NS::Uid(id), #name, cat, singleton, readable }; \
191     }
192 
193 #define META_REGISTER_IMPL_CLASS3(singleton, name, id, cat) META_REGISTER_IMPL_CLASS4(singleton, name, id, cat, #name)
194 
195 #define META_REGISTER_IMPL_CLASS(singleton, ...)                                                         \
196     META_EXPAND(META_GET_MACRO4_IMPL(__VA_ARGS__, META_REGISTER_IMPL_CLASS4, META_REGISTER_IMPL_CLASS3)( \
197         singleton, __VA_ARGS__))
198 
199 #define META_REGISTER_CLASS(...) META_REGISTER_IMPL_CLASS(false, __VA_ARGS__)
200 #define REGISTER_CLASS(...) META_REGISTER_CLASS(__VA_ARGS__)
201 
202 /**
203  * @brief Register UID and category for class name. This tells there exists a singleton object with this UID which can
204  * be accessed via ObjectRegistry.
205  */
206 #define META_REGISTER_SINGLETON_CLASS(...) META_REGISTER_IMPL_CLASS(true, __VA_ARGS__)
207 #define REGISTER_SINGLETON_CLASS(...) META_REGISTER_SINGLETON_CLASS(__VA_ARGS__)
208 
209 /**
210  * @brief Register UID for interface type. This will associate interface name to UID.
211  * Note: One can use this with two parameter version of META_INTERFACE macro, or
212  * alternatively there is no need for this if using the three parameter version of META_INTERFACE.
213  * Example:
214  *     META_REGISTER_INTERFACE(IAttach, "2cc0d7b9-ccec-474e-acdd-d06fb5aeb714")
215  *     class IAttach : public CORE_NS::IInterface {
216  *         META_INTERFACE(CORE_NS::IInterface, IAttach)
217  *   Here the META_INTERFACE macro will find the UID using the name "IAttach".
218  */
219 #define META_REGISTER_INTERFACE3(name, id, readable)                                                          \
220     namespace InterfaceId {                                                                                   \
221     [[maybe_unused]] inline constexpr ::META_NS::InterfaceInfo name { META_NS::TypeId(id), #name, readable }; \
222     }
223 
224 #define META_REGISTER_INTERFACE2(name, id) META_REGISTER_INTERFACE3(name, id, #name)
225 
226 #define META_REGISTER_INTERFACE(...) \
227     META_EXPAND(META_GET_MACRO3_IMPL(__VA_ARGS__, META_REGISTER_INTERFACE3, META_REGISTER_INTERFACE2)(__VA_ARGS__))
228 
229 #define REGISTER_INTERFACE(...) META_REGISTER_INTERFACE(__VA_ARGS__)
230 
231 META_END_NAMESPACE()
232 
233 #endif
234