1 /*
2 * Copyright (c) 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 MAPLE_UTIL_INCLUDE_SAFE_CAST_H
17 #define MAPLE_UTIL_INCLUDE_SAFE_CAST_H
18 #include "utils/meta.h"
19
20 namespace maple {
21 template <typename ToT>
22 struct SafeCastCondition : public std::false_type {
23 };
24
25 #define REGISTER_SAFE_CAST(type, condition) \
26 template <> \
27 struct SafeCastCondition<type> : public std::true_type { \
28 template <typename FromT> \
29 static inline bool DoIt(const FromT &from) \
30 { \
31 return (condition); \
32 } \
33 }
34
35 namespace impl {
36 template <typename ToT, typename FromT, typename = std::enable_if_t<std::is_base_of<FromT, ToT>::value>>
37 struct InstanceOfImpl {
DoItmaple::impl::InstanceOfImpl38 static inline bool DoIt(const FromT &from)
39 {
40 return (SafeCastCondition<ToT>::DoIt(from));
41 }
42 };
43
44 template <typename ToT, typename FromT>
45 struct InstanceOfImpl<ToT, FromT, typename std::enable_if_t<std::is_base_of<ToT, FromT>::value>> {
DoItmaple::impl::InstanceOfImpl46 static inline bool DoIt(const FromT &)
47 {
48 return true;
49 }
50 };
51
52 template <typename ToT, typename FromT>
53 struct EnabledSafeCast : public utils::meta_or<std::is_base_of<ToT, FromT>, SafeCastCondition<ToT>>::type {
54 };
55 } // namespace impl
56
57 template <typename ToT, typename FromT, typename = std::enable_if_t<impl::EnabledSafeCast<ToT, FromT>::value>>
instance_of(FromT &from)58 inline bool instance_of(FromT &from)
59 {
60 return impl::InstanceOfImpl<ToT, FromT>::DoIt(from);
61 }
62
63 template <typename ToT, typename FromT, typename = std::enable_if_t<impl::EnabledSafeCast<ToT, FromT>::value>>
instance_of(FromT *from)64 inline bool instance_of(FromT *from)
65 {
66 return (from != nullptr && instance_of<ToT>(*from));
67 }
68
69 template <typename ToT, typename FromT,
70 typename RetT = std::conditional_t<
71 std::is_const<FromT>::value || std::is_const<std::remove_pointer_t<ToT>>::value,
72 std::add_pointer_t<std::add_const_t<std::remove_cv_t<ToT>>>, std::add_pointer_t<std::remove_cv_t<ToT>>>,
73 typename = std::enable_if_t<impl::EnabledSafeCast<ToT, FromT>::value>>
safe_cast(FromT &from)74 inline RetT safe_cast(FromT &from)
75 {
76 return (instance_of<ToT>(from) ? static_cast<RetT>(&from) : nullptr);
77 }
78
79 template <typename ToT, typename FromT,
80 typename RetT = std::conditional_t<
81 std::is_const<FromT>::value || std::is_const<std::remove_pointer_t<ToT>>::value,
82 std::add_pointer_t<std::add_const_t<std::remove_cv_t<ToT>>>, std::add_pointer_t<std::remove_cv_t<ToT>>>,
83 typename = std::enable_if_t<impl::EnabledSafeCast<ToT, FromT>::value>>
safe_cast(FromT *from)84 inline RetT safe_cast(FromT *from)
85 {
86 return (instance_of<ToT>(from) ? static_cast<RetT>(from) : nullptr);
87 }
88 } // namespace maple
89 #endif // MAPLE_UTIL_INCLUDE_SAFE_CAST_H