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