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 META_INTERFACE_TYPED_PROPERTY_H
17 #define META_INTERFACE_TYPED_PROPERTY_H
18 
19 #include <meta/base/types.h>
20 #include <meta/interface/detail/property.h>
21 
META_BEGIN_NAMESPACE()22 META_BEGIN_NAMESPACE()
23 
24 template<typename Type>
25 class Property {
26 public:
27     using ValueType = BASE_NS::remove_const_t<Type>;
28     using PropertyInterfaceType = BASE_NS::conditional_t<BASE_NS::is_const_v<Type>, const IProperty, IProperty>;
29     using PropertyType = BASE_NS::shared_ptr<PropertyInterfaceType>;
30 
31     Property() = default;
32     Property(nullptr_t) {}
33 
34     template<typename Prop, typename = BASE_NS::enable_if_t<BASE_NS::is_convertible_v<Prop*, PropertyInterfaceType*>>>
35     Property(BASE_NS::shared_ptr<Prop> p) : p_(BASE_NS::move(p))
36     {
37         if (p_ && !p_->IsCompatible(UidFromType<ValueType>())) {
38             CORE_LOG_W("Not compatible any for given property type [%s]", p_->GetName().c_str());
39             p_ = nullptr;
40         }
41     }
42     template<typename Prop, typename = BASE_NS::enable_if_t<BASE_NS::is_convertible_v<Prop*, PropertyInterfaceType*>>>
43     Property(NoCheckT, BASE_NS::shared_ptr<Prop> p) : p_(p)
44     {}
45 
46     template<typename PType,
47         typename = BASE_NS::enable_if_t<BASE_NS::is_const_v<Type> && BASE_NS::is_same_v<PType, ValueType>>>
48     Property(const Property<PType>& p) : Property(p.GetProperty())
49     {}
50 
51     bool IsValid() const
52     {
53         return p_ != nullptr;
54     }
55 
56     explicit operator bool() const
57     {
58         return IsValid();
59     }
60 
61     TypedPropertyLock<Type> operator->() const
62     {
63         return GetLockedAccess();
64     }
65 
66     TypedPropertyLock<Type> GetLockedAccess() const
67     {
68         return TypedPropertyLock<Type>(p_.get());
69     }
70 
71     PropertyInterface<Type> GetUnlockedAccess() const
72     {
73         return PropertyInterface<Type>(p_.get());
74     }
75 
76     operator IProperty::ConstPtr() const
77     {
78         return p_;
79     }
80 
81     operator IProperty::Ptr()
82     {
83         return p_;
84     }
85 
86     operator IProperty::ConstWeakPtr() const
87     {
88         return p_;
89     }
90 
91     operator IProperty::WeakPtr()
92     {
93         return p_;
94     }
95 
96     PropertyType GetProperty() const
97     {
98         return p_;
99     }
100 
101 private:
102     PropertyType p_;
103 };
104 
105 template<typename T>
106 using ConstProperty = Property<const T>;
107 
108 template<typename T>
109 inline bool operator==(const Property<T>& l, const Property<T>& r)
110 {
111     return l.GetProperty() == r.GetProperty();
112 }
113 
114 template<typename T>
115 inline bool operator!=(const Property<T>& l, const Property<T>& r)
116 {
117     return !(l == r);
118 }
119 
META_END_NAMESPACE()120 META_END_NAMESPACE()
121 
122 // NOLINTBEGIN(readability-identifier-naming) to keep std like syntax
123 
124 template<typename T, typename S>
125 BASE_NS::shared_ptr<T> interface_pointer_cast(const META_NS::Property<S>& p)
126 {
127     static_assert(META_NS::HasGetInterfaceMethod_v<T>, "T::GetInterface not defined");
128     return interface_pointer_cast<T>(p.GetProperty());
129 }
130 
131 template<typename T, typename S>
interface_cast(const META_NS::Property<S> & p)132 T* interface_cast(const META_NS::Property<S>& p)
133 {
134     static_assert(META_NS::HasGetInterfaceMethod_v<T>, "T::GetInterface not defined");
135     return interface_cast<T>(p.GetProperty());
136 }
137 
138 // NOLINTEND(readability-identifier-naming) to keep std like syntax
139 
140 #endif
141