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