1 /*
2  * Copyright (c) 2021-2023 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 FOUNDATION_ACE_FRAMEWORKS_BASE_MEMORY_TYPE_INFO_BASE_H
17 #define FOUNDATION_ACE_FRAMEWORKS_BASE_MEMORY_TYPE_INFO_BASE_H
18 
19 #include <string>
20 
21 #include "base/memory/memory_monitor_def.h"
22 
23 // Generate 'TypeInfo' for each classes.
24 // And using hash code of its name for 'TypeId'.
25 #define DECLARE_CLASS_TYPE_INFO(classname)                                              \
26 public:                                                                                 \
27     static const char* TypeName()                                                       \
28     {                                                                                   \
29         return #classname;                                                              \
30     }                                                                                   \
31     static TypeInfoBase::IdType TypeId()                                                \
32     {                                                                                   \
33         static TypeInfoBase::IdType myTypeId = std::hash<std::string> {}(TypeName());   \
34         return myTypeId;                                                                \
35     }                                                                                   \
36     DECLARE_CLASS_TYPE_SIZE(classname)
37 
38 // Integrate it into class declaration to support 'DynamicCast'.
39 #define DECLARE_RELATIONSHIP_OF_CLASSES(classname, ...) DECLARE_CLASS_TYPE_INFO(classname)            \
40 protected:                                                                                            \
41     template<class __T, class __O, class... __V>                                                      \
42     uintptr_t TrySafeCastById(TypeInfoBase::IdType id) const                                          \
43     {                                                                                                 \
44         VERIFY_DECLARED_CLASS(__T);                                                                   \
45         uintptr_t ptr = __T::SafeCastById(id);                                                        \
46         return ptr != 0 ? ptr : TrySafeCastById<__O, __V...>(id);                                     \
47     }                                                                                                 \
48     template<class __T>                                                                               \
49     uintptr_t TrySafeCastById(TypeInfoBase::IdType id) const                                          \
50     {                                                                                                 \
51         VERIFY_DECLARED_CLASS(__T);                                                                   \
52         return __T::SafeCastById(id);                                                                 \
53     }                                                                                                 \
54     uintptr_t SafeCastById(TypeInfoBase::IdType id) const override                                    \
55     {                                                                                                 \
56         return id == TypeId() ? reinterpret_cast<uintptr_t>(this) : TrySafeCastById<__VA_ARGS__>(id); \
57     }                                                                                                 \
58     TypeInfoBase::IdType GetTypeId() const override                                                   \
59     {                                                                                                 \
60         return TypeId();                                                                              \
61     }                                                                                                 \
62     const char* GetTypeName() const override                                                          \
63     {                                                                                                 \
64         return TypeName();                                                                            \
65     }                                                                                                 \
66     DECLARE_CLASS_GET_TYPE_SIZE(classname)
67 
68 namespace OHOS::Ace {
69 
70 // Define the base class, inherit this class to support partial 'RTTI' feature.
71 class TypeInfoBase {
72 public:
73     friend class TypeInfoHelper;
74     virtual ~TypeInfoBase() = default;
75 
76     using IdType = std::size_t;
77     DECLARE_CLASS_TYPE_INFO(TypeInfoBase);
78 
79 protected:
SafeCastById(IdType id)80     virtual uintptr_t SafeCastById(IdType id) const
81     {
82         return id == TypeId() ? reinterpret_cast<uintptr_t>(this) : 0;
83     }
84 
85     virtual IdType GetTypeId() const = 0;
86     virtual const char* GetTypeName() const = 0;
GetTypeSize()87     virtual size_t GetTypeSize() const { return 0; }
88 };
89 
90 class TypeInfoHelper final {
91 public:
92     TypeInfoHelper() = delete;
93     ~TypeInfoHelper() = delete;
94 
95     // Convert pointer of instance inherited from 'TypeInfoBase'.
96     // Notice: Result SHOULD BE checked with 'nullptr', because 'DynamicCast' might be failed.
97     template<class T>
DynamicCast(TypeInfoBase * rawPtr)98     static T* DynamicCast(TypeInfoBase* rawPtr)
99     {
100         VERIFY_DECLARED_CLASS(T);
101         return rawPtr != nullptr ? reinterpret_cast<T*>(rawPtr->SafeCastById(T::TypeId())) : nullptr;
102     }
103     template<class T>
DynamicCast(const TypeInfoBase * rawPtr)104     static const T* DynamicCast(const TypeInfoBase* rawPtr)
105     {
106         VERIFY_DECLARED_CLASS(T);
107         return rawPtr != nullptr ? reinterpret_cast<const T*>(rawPtr->SafeCastById(T::TypeId())) : nullptr;
108     }
109 
110     // Get type info by instance.
TypeId(const TypeInfoBase * rawPtr)111     static TypeInfoBase::IdType TypeId(const TypeInfoBase* rawPtr)
112     {
113         return rawPtr != nullptr ? rawPtr->GetTypeId() : 0;
114     }
TypeId(const TypeInfoBase & instance)115     static TypeInfoBase::IdType TypeId(const TypeInfoBase& instance)
116     {
117         return TypeId(&instance);
118     }
TypeName(const TypeInfoBase * rawPtr)119     static const char* TypeName(const TypeInfoBase* rawPtr)
120     {
121         return rawPtr != nullptr ? rawPtr->GetTypeName() : nullptr;
122     }
TypeName(const TypeInfoBase & instance)123     static const char* TypeName(const TypeInfoBase& instance)
124     {
125         return TypeName(&instance);
126     }
TypeSize(const TypeInfoBase * rawPtr)127     static size_t TypeSize(const TypeInfoBase* rawPtr)
128     {
129         return rawPtr != nullptr ? rawPtr->GetTypeSize() : 0;
130     }
TypeSize(const TypeInfoBase & instance)131     static size_t TypeSize(const TypeInfoBase& instance)
132     {
133         return TypeSize(&instance);
134     }
135 
136     // Get type info by type itself.
137     template<class T>
TypeId()138     static TypeInfoBase::IdType TypeId()
139     {
140         return T::TypeId();
141     }
142     template<class T>
TypeName()143     static const char* TypeName()
144     {
145         return T::TypeName();
146     }
147 
148     // Check whether instance is the specified type
149     template<class T>
InstanceOf(const TypeInfoBase * rawPtr)150     static bool InstanceOf(const TypeInfoBase* rawPtr)
151     {
152         return DynamicCast<T>(rawPtr) != nullptr;
153     }
154     template<class T>
InstanceOf(const TypeInfoBase & instance)155     static bool InstanceOf(const TypeInfoBase& instance)
156     {
157         return DynamicCast<T>(&instance) != nullptr;
158     }
159 };
160 
161 } // namespace OHOS::Ace
162 
163 #endif // FOUNDATION_ACE_FRAMEWORKS_BASE_MEMORY_TYPE_INFO_BASE_H
164