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_ANY_H
17 #define META_INTERFACE_ANY_H
18 
19 #include <core/plugin/intf_interface.h>
20 
21 #include <meta/base/expected.h>
22 #include <meta/base/ids.h>
23 #include <meta/base/interface_macros.h>
24 #include <meta/base/namespace.h>
25 #include <meta/base/types.h>
26 
27 META_BEGIN_NAMESPACE()
28 
29 META_REGISTER_INTERFACE(IAny, "9e6d554e-3647-4040-a5c4-ea299fa85b8f")
30 META_REGISTER_INTERFACE(IArrayAny, "d3c49aa9-9314-4680-b23a-7d2a24a0af30")
31 
32 enum class AnyReturn {
33     NOTHING_TO_DO = 2,
34     SUCCESS = 1,
35     UNUSED = 0,
36     FAIL = -1,
37     INVALID_ARGUMENT = -2,
38     INCOMPATIBLE_TYPE = -3,
39     NOT_SUPPORTED = -4,
40     RECURSIVE_CALL = -5
41 };
42 inline bool operator<(AnyReturn l, AnyReturn r)
43 {
44     return int64_t(l) < int64_t(r);
45 }
46 inline bool operator>(AnyReturn l, AnyReturn r)
47 {
48     return int64_t(l) > int64_t(r);
49 }
50 
51 using AnyReturnValue = ReturnValue<AnyReturn>;
52 
53 enum class CompatibilityDirection { GET, SET, BOTH };
54 enum class TypeIdRole { CURRENT, ITEM, ARRAY };
55 enum class CloneValueType { COPY_VALUE, DEFAULT_VALUE };
56 
57 struct AnyCloneOptions {
58     /** Should value be cloned. Ignored if role != TypeIdRole::CURRENT */
59     CloneValueType value { CloneValueType::COPY_VALUE };
60     /** Type of Any (same as source, item or array type) the clone should be. */
61     TypeIdRole role { TypeIdRole::CURRENT };
62 };
63 
64 class IAny : public CORE_NS::IInterface {
65     META_INTERFACE(CORE_NS::IInterface, IAny)
66 public:
67     virtual ObjectId GetClassId() const = 0;
68     virtual const BASE_NS::array_view<const TypeId> GetCompatibleTypes(CompatibilityDirection) const = 0;
69     virtual AnyReturnValue GetData(const TypeId& id, void* data, size_t size) const = 0;
70     virtual AnyReturnValue SetData(const TypeId& id, const void* data, size_t size) = 0;
71     virtual AnyReturnValue CopyFrom(const IAny& any) = 0;
72     virtual IAny::Ptr Clone(const AnyCloneOptions& options) const = 0;
73     virtual TypeId GetTypeId(TypeIdRole role) const = 0;
74     virtual BASE_NS::string GetTypeIdString() const = 0;
75 
GetTypeId()76     TypeId GetTypeId() const
77     {
78         return GetTypeId(TypeIdRole::CURRENT);
79     }
IsArray()80     bool IsArray() const
81     {
82         return GetTypeId(TypeIdRole::CURRENT) == GetTypeId(TypeIdRole::ARRAY);
83     }
Clone()84     IAny::Ptr Clone() const
85     {
86         return Clone({ CloneValueType::COPY_VALUE });
87     }
Clone(bool withValue)88     IAny::Ptr Clone(bool withValue) const
89     {
90         return Clone({ withValue ? CloneValueType::COPY_VALUE : CloneValueType::DEFAULT_VALUE });
91     }
92     template<typename T>
GetValue(T & value)93     AnyReturnValue GetValue(T& value) const
94     {
95         return GetData(UidFromType<T>(), &value, sizeof(T)); /*NOLINT(bugprone-sizeof-expression)*/
96     }
97     template<typename T>
SetValue(const T & value)98     AnyReturnValue SetValue(const T& value)
99     {
100         return SetData(UidFromType<T>(), &value, sizeof(T)); /*NOLINT(bugprone-sizeof-expression)*/
101     }
102 };
103 
104 class IArrayAny : public IAny {
105     META_INTERFACE(IAny, IArrayAny)
106 public:
107     using IndexType = size_t;
108 
109     virtual AnyReturnValue GetDataAt(size_t index, const TypeId& id, void* data, size_t size) const = 0;
110     virtual AnyReturnValue SetDataAt(size_t index, const TypeId& id, const void* data, size_t size) = 0;
111     virtual AnyReturnValue SetAnyAt(IndexType index, const IAny& value) = 0;
112     virtual AnyReturnValue GetAnyAt(IndexType index, IAny& value) const = 0;
113     virtual AnyReturnValue InsertAnyAt(IndexType index, const IAny& value) = 0;
114     virtual AnyReturnValue RemoveAt(IndexType index) = 0;
115     virtual void RemoveAll() = 0;
116 
117     virtual IndexType GetSize() const = 0;
118 
119     template<typename T>
GetValueAt(IndexType index,T & value)120     AnyReturnValue GetValueAt(IndexType index, T& value) const
121     {
122         return GetDataAt(index, UidFromType<T>(), &value, sizeof(T)); /*NOLINT(bugprone-sizeof-expression)*/
123     }
124     template<typename T>
SetValueAt(IndexType index,const T & value)125     AnyReturnValue SetValueAt(IndexType index, const T& value)
126     {
127         return SetDataAt(index, UidFromType<T>(), &value, sizeof(T)); /*NOLINT(bugprone-sizeof-expression)*/
128     }
129 };
130 
IsArray(const IAny & any)131 inline bool IsArray(const IAny& any)
132 {
133     return any.GetInterface<IArrayAny>() != nullptr;
134 }
135 
IsArray(const IAny::ConstPtr & any)136 inline bool IsArray(const IAny::ConstPtr& any)
137 {
138     return any && any->GetInterface<IArrayAny>() != nullptr;
139 }
140 
141 template<typename T>
142 inline T GetValue(const IAny& any, NonDeduced_t<T> defaultValue = {})
143 {
144     T t;
145     if (!any.GetValue(t)) {
146         t = defaultValue;
147     }
148     return t;
149 }
150 
151 template<typename T>
152 inline T GetValueAt(const IArrayAny& array, IArrayAny::IndexType index, NonDeduced_t<T> defaultValue = {})
153 {
154     T t;
155     if (!array.GetValueAt(index, t)) {
156         t = defaultValue;
157     }
158     return t;
159 }
160 
161 inline bool IsCompatible(const IAny& any, const TypeId& uid, CompatibilityDirection dir = CompatibilityDirection::BOTH)
162 {
163     for (auto&& v : any.GetCompatibleTypes(dir)) {
164         if (uid == v) {
165             return true;
166         }
167     }
168     return false;
169 }
170 
171 inline bool IsCompatibleWith(
172     const IAny& any, const IAny& other, CompatibilityDirection dir = CompatibilityDirection::BOTH)
173 {
174     for (auto&& v : other.GetCompatibleTypes(dir)) {
175         if (IsCompatible(any, v, dir)) {
176             return true;
177         }
178     }
179     return false;
180 }
181 
182 template<typename T>
183 inline bool IsCompatibleWith(const IAny& any, CompatibilityDirection dir = CompatibilityDirection::BOTH)
184 {
185     return IsCompatible(any, UidFromType<BASE_NS::remove_const_t<BASE_NS::remove_reference_t<T>>>(), dir);
186 }
187 
IsSetCompatible(const IAny & any,const TypeId & uid)188 inline bool IsSetCompatible(const IAny& any, const TypeId& uid)
189 {
190     return IsCompatible(any, uid, CompatibilityDirection::SET);
191 }
192 
IsGetCompatible(const IAny & any,const TypeId & uid)193 inline bool IsGetCompatible(const IAny& any, const TypeId& uid)
194 {
195     return IsCompatible(any, uid, CompatibilityDirection::GET);
196 }
197 
198 template<typename T>
IsSetCompatibleWith(const IAny & any)199 inline bool IsSetCompatibleWith(const IAny& any)
200 {
201     return IsCompatibleWith<T>(any, CompatibilityDirection::SET);
202 }
203 
204 template<typename T>
IsGetCompatibleWith(const IAny & any)205 inline bool IsGetCompatibleWith(const IAny& any)
206 {
207     return IsCompatibleWith<T>(any, CompatibilityDirection::GET);
208 }
209 
210 META_END_NAMESPACE()
211 
212 META_INTERFACE_TYPE(META_NS::IAny)
213 META_INTERFACE_TYPE(META_NS::IArrayAny)
214 
215 #endif
216