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