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_BASE_INTERFACE_UTILS_H
17 #define META_BASE_INTERFACE_UTILS_H
18 
19 #include <base/containers/vector.h>
20 #include <core/plugin/intf_interface.h>
21 
22 #include <meta/base/ids.h>
23 #include <meta/base/shared_ptr.h>
24 
META_BEGIN_NAMESPACE()25 META_BEGIN_NAMESPACE()
26 
27 /**
28  * @brief Checks if object implements any of the given interfaces.
29  * @note The function returns false for a null object, regardless of uids.
30  * @note If the object is valid but the uid list is empty, the function returns true.
31  * @param object The object to check.
32  * @param uids The uids to check against.
33  * @return True if the object implements any of the uids.
34  */
35 static inline bool ObjectImplementsAny(
36     const BASE_NS::shared_ptr<const CORE_NS::IInterface>& object, const BASE_NS::array_view<const TypeId>& ids) noexcept
37 {
38     if (object) {
39         for (const auto& id : ids) {
40             if (object->GetInterface(id.ToUid())) {
41                 return true;
42             }
43         }
44         return ids.empty();
45     }
46     return false;
47 }
48 
49 /**
50  * @brief Checks if object implements all of the given interfaces.
51  * @note The function returns false for a null object, regardless of uids.
52  * @note If the object is valid but the uid list is empty, the function returns true.
53  * @param object The object to check.
54  * @param uids The uids to check against.
55  * @return True if the object implements all of the uids.
56  */
ObjectImplementsAll(const BASE_NS::shared_ptr<const CORE_NS::IInterface> & object,const BASE_NS::array_view<const TypeId> & ids)57 static inline bool ObjectImplementsAll(
58     const BASE_NS::shared_ptr<const CORE_NS::IInterface>& object, const BASE_NS::array_view<const TypeId>& ids) noexcept
59 {
60     if (object) {
61         for (const auto& id : ids) {
62             if (!object->GetInterface(id.ToUid())) {
63                 return false;
64             }
65         }
66         return true;
67     }
68     return false;
69 }
70 
71 /**
72  * @brief Checks whether a given object implements one/all of a given set of interface UIDs.
73  * @note The function returns false for a null object, regardless of uids.
74  * @note If the object is valid but the uid list is empty, the function returns true.
75  * @param object The object to check.
76  * @param uids A list of Uids to check against.
77  * @param strict If true, the object must implement all listed Uids. If false, it is enough to implement one.
78  * @return True if object implements given requirements, false otherwise.
79  */
CheckInterfaces(const BASE_NS::shared_ptr<const CORE_NS::IInterface> & object,const BASE_NS::array_view<const TypeId> & ids,bool strict)80 static inline bool CheckInterfaces(const BASE_NS::shared_ptr<const CORE_NS::IInterface>& object,
81     const BASE_NS::array_view<const TypeId>& ids, bool strict) noexcept
82 {
83     return strict ? ObjectImplementsAll(object, ids) : ObjectImplementsAny(object, ids);
84 }
85 
86 /**
87  * @brief Checks if a list of uids matches a given set of requirements.
88  * @param uids The uid list to check against.
89  * @param reqs A uid list which must be found from <param>uids</param>.
90  * @param strict If true, all of reqs must be found from uids. If false, one match is enough.
91  * @return True if uids fulfills reqs, false otherwise.
92  */
CheckInterfaces(const BASE_NS::vector<BASE_NS::Uid> & uids,const BASE_NS::vector<BASE_NS::Uid> & reqs,bool strict)93 static bool CheckInterfaces(
94     const BASE_NS::vector<BASE_NS::Uid>& uids, const BASE_NS::vector<BASE_NS::Uid>& reqs, bool strict) noexcept
95 {
96     if (uids.empty() && !reqs.empty()) {
97         return false;
98     }
99     if (reqs.empty()) {
100         return true;
101     }
102     size_t matches = strict ? reqs.size() : 1;
103     for (auto&& uid : uids) {
104         for (auto&& req : reqs) {
105             if (req == uid) {
106                 if (--matches == 0) {
107                     return true;
108                 }
109                 break;
110             }
111         }
112     }
113     return false;
114 }
115 
116 /**
117  * @brief Returns a vector containing all of the source vector objects which implement To::UID casted
118  *        to To::Ptr.
119  * @note The result can contain less items than the input if all items of input do not implement To::UID.
120  *       The result will never contain more items than input.
121  * @param from The vector to convert from.
122  */
123 template<class To, class From>
PtrArrayCast(BASE_NS::vector<From> && from)124 BASE_NS::vector<typename To::Ptr> PtrArrayCast(BASE_NS::vector<From>&& from)
125 {
126     static_assert(IsKindOfPointer_v<From>, "Conversion source array must contain shared_ptrs.");
127     static_assert(IsKindOfInterface_v<To>, "Conversion target type must be an IInterface.");
128     using ToPtr = typename To::Ptr;
129     if constexpr (BASE_NS::is_same_v<ToPtr, From>) {
130         return BASE_NS::move(from);
131     }
132     BASE_NS::vector<ToPtr> converted;
133     converted.reserve(from.size());
134     for (auto&& obj : from) {
135         if (auto t = interface_pointer_cast<To>(obj)) {
136             converted.emplace_back(BASE_NS::move(t));
137         }
138     }
139     return converted;
140 }
141 
142 META_END_NAMESPACE()
143 
144 #endif // META_BASE_INTERFACE_UTILS_H
145