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 OHOS_FFI_RUNTIMETYPE_H
17 #define OHOS_FFI_RUNTIMETYPE_H
18 
19 #include <cstdint>
20 #include <cstring>
21 #include <iostream>
22 #include <vector>
23 
24 namespace OHOS::FFI {
25 
26 class TypeBase;
27 
28 class RuntimeType final {
29 public:
Create(const char * className)30     static RuntimeType Create(const char* className)
31     {
32         return RuntimeType(className);
33     }
34     template<typename Derive>
Create(const char * className)35     static RuntimeType Create(const char* className)
36     {
37         auto result = Create(className);
38         result.parents_.push_back(Derive::GetClassType());
39         return result;
40     }
41     template<typename... Lists, typename Derive>
Create(const char * className)42     static RuntimeType Create(const char* className)
43     {
44         auto result = Create<Lists...>(className);
45         result.parents_.push_back(Derive::GetClassType());
46         return result;
47     }
48 
IsType(RuntimeType * target)49     bool IsType(RuntimeType* target)
50     {
51         if (target == nullptr) {
52             return false;
53         }
54 
55         if (strcmp(this->GetTypeName(), target->GetTypeName())) {
56             return true;
57         }
58         for (auto parent : parents_) {
59             if (parent->IsType(target)) {
60                 return true;
61             }
62         }
63         return false;
64     }
65 
GetTypeName()66     const char* GetTypeName() const
67     {
68         return name_;
69     }
70 
71 private:
RuntimeType(const char * name)72     explicit RuntimeType(const char* name) : name_(name) {}
73     const char* name_;
74     std::vector<RuntimeType*> parents_;
75 };
76 
77 #define DECL_TYPE(className, inheritedClasses...)                                                                 \
78 private:                                                                                                          \
79     friend class OHOS::FFI::RuntimeType;                                                                          \
80     friend class OHOS::FFI::TypeBase;                                                                             \
81     static OHOS::FFI::RuntimeType* GetClassType()                                                                 \
82     {                                                                                                             \
83         static OHOS::FFI::RuntimeType runtimeType = OHOS::FFI::RuntimeType::Create<inheritedClasses>(#className); \
84         return &runtimeType;                                                                                      \
85     }                                                                                                             \
86                                                                                                                   \
87 public:                                                                                                           \
88     OHOS::FFI::RuntimeType* GetRuntimeType() override                                                             \
89     {                                                                                                             \
90         return GetClassType();                                                                                    \
91     }
92 
93 class TypeBase {
94 public:
95     virtual ~TypeBase() = default;
GetRuntimeType()96     virtual RuntimeType* GetRuntimeType()
97     {
98         return GetClassType();
99     }
100 
101     template<class O>
DynamicCast()102     O* DynamicCast()
103     {
104         static_assert(std::is_base_of_v<TypeBase, O>, "O must derived from TypeBase");
105         if (GetRuntimeType()->IsType(O::GetClassType())) {
106             return static_cast<O*>(this);
107         }
108         return nullptr;
109     }
110 
111 private:
112     friend class RuntimeType;
113 
GetClassType()114     static RuntimeType* GetClassType()
115     {
116         static RuntimeType runtimeType = RuntimeType::Create("TypeBase");
117         return &runtimeType;
118     }
119 };
120 } // namespace OHOS::FFI
121 #endif // OHOS_FFI_RUNTIMETYPE_H
122