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 #ifndef META_INTERFACE_DETAIL_ANY_H
16 #define META_INTERFACE_DETAIL_ANY_H
17
18 #include <meta/base/interface_traits.h>
19 #include <meta/interface/detail/any_pointer_compatibility.h>
20 #include <meta/interface/interface_helpers.h>
21 #include <meta/interface/intf_any.h>
22 #include <meta/interface/intf_value.h>
23
24 META_BEGIN_NAMESPACE()
25
26 constexpr char BUILTIN_ANY_TAG[] = "BuiltAny";
27 constexpr char BUILTIN_ARRAY_ANY_TAG[] = "ArrayAny";
28
29 template<typename Type>
30 class BaseTypedAny : public IntroduceInterfaces<IAny, IValue> {
31 public:
32 static constexpr TypeId TYPE_ID = UidFromType<Type>();
33 static constexpr bool IS_PTR_TYPE = IsInterfacePtr_v<Type>;
34
StaticGetClassId()35 static constexpr ObjectId StaticGetClassId()
36 {
37 return MakeUid<Type>(BUILTIN_ANY_TAG);
38 }
39
GetClassId()40 ObjectId GetClassId() const override
41 {
42 return StaticGetClassId();
43 }
44
GetCompatibleTypes(CompatibilityDirection dir)45 const BASE_NS::array_view<const TypeId> GetCompatibleTypes(CompatibilityDirection dir) const override
46 {
47 if constexpr (IS_PTR_TYPE) {
48 return AnyPC<Type>::template GetCompatibleTypes<Type>(dir);
49 }
50
51 static constexpr TypeId uids[] = { TYPE_ID };
52 return uids;
53 }
GetData(const TypeId & id,void * data,size_t size)54 AnyReturnValue GetData(const TypeId& id, void* data, size_t size) const override
55 {
56 if (IsValidGetArgs(id, data, size)) {
57 if constexpr (IS_PTR_TYPE) {
58 using PCType = AnyPC<Type>;
59 using IIType = typename PCType::IIType;
60 auto ret = PCType::GetData(id, data, interface_pointer_cast<IIType>(InternalGetValue()));
61 if (ret) {
62 return ret;
63 }
64 }
65
66 *static_cast<Type*>(data) = InternalGetValue();
67 return AnyReturn::SUCCESS;
68 }
69 return AnyReturn::INVALID_ARGUMENT;
70 }
SetData(const TypeId & id,const void * data,size_t size)71 AnyReturnValue SetData(const TypeId& id, const void* data, size_t size) override
72 {
73 if (IsValidSetArgs(id, data, size)) {
74 if constexpr (IS_PTR_TYPE) {
75 using PCType = AnyPC<Type>;
76 typename PCType::IIPtrType p;
77 if (PCType::SetData(id, data, p)) {
78 if (auto ptr = interface_pointer_cast<typename Type::element_type>(p); ptr || !p) {
79 return InternalSetValue(ptr);
80 }
81 }
82 }
83 return InternalSetValue(*static_cast<const Type*>(data));
84 }
85 return AnyReturn::INVALID_ARGUMENT;
86 }
CopyFrom(const IAny & any)87 AnyReturnValue CopyFrom(const IAny& any) override
88 {
89 if constexpr (IS_PTR_TYPE) {
90 typename AnyPC<Type>::IIPtrType p;
91 if (any.GetValue(p)) {
92 if (auto ptr = interface_pointer_cast<typename Type::element_type>(p); ptr || !p) {
93 return InternalSetValue(ptr);
94 }
95 }
96 } else {
97 if (META_NS::IsCompatible(any, TYPE_ID, CompatibilityDirection::GET)) {
98 Type value;
99 if (any.GetValue(value)) {
100 return InternalSetValue(value);
101 }
102 }
103 }
104 return AnyReturn::FAIL;
105 }
106
GetTypeId(TypeIdRole role)107 TypeId GetTypeId(TypeIdRole role) const override
108 {
109 if (role == TypeIdRole::ARRAY) {
110 return ArrayUidFromType<Type>();
111 }
112 if (role == TypeIdRole::ITEM) {
113 return ItemUidFromType<Type>();
114 }
115 return TYPE_ID;
116 }
GetTypeId()117 TypeId GetTypeId() const
118 {
119 return TYPE_ID;
120 }
GetTypeIdString()121 BASE_NS::string GetTypeIdString() const override
122 {
123 return MetaType<Type>::name;
124 }
125 using IAny::SetValue;
SetValue(const IAny & value)126 AnyReturnValue SetValue(const IAny& value) override
127 {
128 return CopyFrom(value);
129 }
130 using IAny::GetValue;
GetValue()131 const IAny& GetValue() const override
132 {
133 return *this;
134 }
IsCompatible(const TypeId & id)135 bool IsCompatible(const TypeId& id) const override
136 {
137 return META_NS::IsCompatible(*this, id);
138 }
139
140 protected:
141 virtual AnyReturnValue InternalSetValue(const Type& value) = 0;
142 virtual const Type& InternalGetValue() const = 0;
143
144 private:
IsValidGetArgs(const TypeId & uid,const void * data,size_t size)145 static constexpr bool IsValidGetArgs(const TypeId& uid, const void* data, size_t size)
146 {
147 if constexpr (IS_PTR_TYPE) {
148 if (AnyPC<Type>::IsValidGetArgs(uid, data, size)) {
149 return true;
150 }
151 }
152 return data && sizeof(Type) == size && uid == TYPE_ID; /*NOLINT(bugprone-sizeof-expression)*/
153 }
IsValidSetArgs(const TypeId & uid,const void * data,size_t size)154 static constexpr bool IsValidSetArgs(const TypeId& uid, const void* data, size_t size)
155 {
156 if constexpr (IS_PTR_TYPE) {
157 if (AnyPC<Type>::IsValidSetArgs(uid, data, size)) {
158 return true;
159 }
160 }
161 return data && sizeof(Type) == size && uid == TYPE_ID; /*NOLINT(bugprone-sizeof-expression)*/
162 }
163 };
164
165 template<typename T, bool Compare = HasEqualOperator_v<T>>
166 struct DefaultCompare {
EqualDefaultCompare167 static constexpr bool Equal(const T& v1, const T& v2)
168 {
169 if constexpr (Compare) {
170 return v1 == v2;
171 } else {
172 return false;
173 }
174 }
175 };
176
177 /**
178 * @brief Default IAny implementation which supports a single type.
179 */
180 template<typename Type, typename Compare = DefaultCompare<Type>>
181 class Any : public BaseTypedAny<Type> {
182 using Super = BaseTypedAny<Type>;
183
184 public:
185 explicit Any(Type v = {}) : value_(BASE_NS::move(v)) {}
InternalSetValue(const Type & value)186 AnyReturnValue InternalSetValue(const Type& value) override
187 {
188 if (!Compare::Equal(value, value_)) {
189 value_ = value;
190 return AnyReturn::SUCCESS;
191 }
192 return AnyReturn::NOTHING_TO_DO;
193 }
InternalGetValue()194 const Type& InternalGetValue() const override
195 {
196 return value_;
197 }
198 IAny::Ptr Clone(const AnyCloneOptions& options) const override;
Clone(bool withValue)199 IAny::Ptr Clone(bool withValue) const
200 {
201 return Clone({ withValue ? CloneValueType::COPY_VALUE : CloneValueType::DEFAULT_VALUE });
202 }
203
204 bool operator==(const Any<Type>& other) const noexcept
205 {
206 return (Compare::Equal(other.InternalGetValue(), value_));
207 }
208
209 private:
210 Type value_;
211 };
212
213 template<typename Type>
214 class BaseTypedArrayAny : public IntroduceInterfaces<IArrayAny, IValue> {
215 public:
216 static constexpr TypeId VECTOR_TYPE_ID = UidFromType<BASE_NS::vector<Type>>();
217 static constexpr TypeId ARRAY_TYPE_ID = ArrayUidFromType<Type>();
218 static constexpr TypeId ITEM_TYPE_ID = ItemUidFromType<Type>();
219 static constexpr TypeId TYPE_ID = ARRAY_TYPE_ID;
220 using ItemType = Type;
221 using ArrayType = BASE_NS::vector<Type>;
222
StaticGetClassId()223 static constexpr ObjectId StaticGetClassId()
224 {
225 return MakeUid<Type>(BUILTIN_ARRAY_ANY_TAG);
226 }
227
GetClassId()228 ObjectId GetClassId() const override
229 {
230 return StaticGetClassId();
231 }
232
GetCompatibleTypes(CompatibilityDirection dir)233 const BASE_NS::array_view<const TypeId> GetCompatibleTypes(CompatibilityDirection dir) const override
234 {
235 static constexpr TypeId uids[] = { ARRAY_TYPE_ID, VECTOR_TYPE_ID };
236 return uids;
237 }
GetData(const TypeId & id,void * data,size_t size)238 AnyReturnValue GetData(const TypeId& id, void* data, size_t size) const override
239 {
240 if (IsValidVectorArgs(id, data, size)) {
241 *static_cast<ArrayType*>(data) = InternalGetValue();
242 return AnyReturn::SUCCESS;
243 }
244 if (IsValidArrayArgs(id, data)) {
245 auto& value = InternalGetValue();
246 const auto valueSize = value.size() * sizeof(Type); /*NOLINT(bugprone-sizeof-expression)*/
247 if (size >= valueSize) {
248 BASE_NS::CloneData(data, size, value.data(), valueSize);
249 return AnyReturn::SUCCESS;
250 }
251 }
252 return AnyReturn::INVALID_ARGUMENT;
253 }
SetData(const TypeId & id,const void * data,size_t size)254 AnyReturnValue SetData(const TypeId& id, const void* data, size_t size) override
255 {
256 if (IsValidVectorArgs(id, data, size)) {
257 return InternalSetValue(*static_cast<const ArrayType*>(data));
258 }
259 if (IsValidArrayArgs(id, data)) {
260 auto p = static_cast<const Type*>(data);
261 return InternalSetValue(
262 BASE_NS::vector<Type>(p, p + size / sizeof(Type))); /*NOLINT(bugprone-sizeof-expression)*/
263 }
264 return AnyReturn::INVALID_ARGUMENT;
265 }
CopyFrom(const IAny & any)266 AnyReturnValue CopyFrom(const IAny& any) override
267 {
268 if (META_NS::IsCompatible(any, TYPE_ID, CompatibilityDirection::GET)) {
269 ArrayType value;
270 if (any.GetValue(value)) {
271 return InternalSetValue(value);
272 }
273 }
274 return AnyReturn::FAIL;
275 }
276
GetTypeId(TypeIdRole role)277 TypeId GetTypeId(TypeIdRole role) const override
278 {
279 if (role == TypeIdRole::ARRAY) {
280 return ARRAY_TYPE_ID;
281 }
282 if (role == TypeIdRole::ITEM) {
283 return ITEM_TYPE_ID;
284 }
285 return TYPE_ID;
286 }
GetTypeId()287 TypeId GetTypeId() const
288 {
289 return TYPE_ID;
290 }
GetTypeIdString()291 BASE_NS::string GetTypeIdString() const override
292 {
293 return MetaType<ArrayType>::name;
294 }
295 using IAny::SetValue;
SetValue(const IAny & value)296 AnyReturnValue SetValue(const IAny& value) override
297 {
298 return CopyFrom(value);
299 }
300 using IAny::GetValue;
GetValue()301 const IAny& GetValue() const override
302 {
303 return *this;
304 }
IsCompatible(const TypeId & id)305 bool IsCompatible(const TypeId& id) const override
306 {
307 return META_NS::IsCompatible(*this, id);
308 }
309
310 protected:
311 virtual AnyReturnValue InternalSetValue(const ArrayType& value) = 0;
312 virtual const ArrayType& InternalGetValue() const = 0;
313
314 private:
IsValidVectorArgs(const TypeId & uid,const void * data,size_t size)315 static constexpr bool IsValidVectorArgs(const TypeId& uid, const void* data, size_t size)
316 {
317 return data && sizeof(ArrayType) == size && uid == VECTOR_TYPE_ID;
318 }
IsValidArrayArgs(const TypeId & uid,const void * data)319 static constexpr bool IsValidArrayArgs(const TypeId& uid, const void* data)
320 {
321 return data && uid == ARRAY_TYPE_ID;
322 }
323 };
324
325 /**
326 * @brief Default IArrayAny implementation which supports a single type.
327 */
328 template<typename Type, typename Compare = DefaultCompare<BASE_NS::vector<Type>>>
329 class ArrayAny : public BaseTypedArrayAny<Type> {
330 using Super = BaseTypedArrayAny<Type>;
331 using ArrayType = typename Super::ArrayType;
332 using ItemType = typename Super::ItemType;
333 using Super::ITEM_TYPE_ID;
334 static constexpr auto ITEM_SIZE = sizeof(ItemType); /*NOLINT(bugprone-sizeof-expression)*/
335
336 public:
337 explicit constexpr ArrayAny(ArrayType v = {}) : value_(BASE_NS::move(v)) {}
ArrayAny(const BASE_NS::array_view<const Type> & v)338 explicit constexpr ArrayAny(const BASE_NS::array_view<const Type>& v) : value_(v.begin(), v.end()) {}
339 #ifdef BASE_VECTOR_HAS_INITIALIZE_LIST
ArrayAny(std::initializer_list<Type> v)340 constexpr ArrayAny(std::initializer_list<Type> v) : value_(ArrayType(v)) {}
341 #endif
342
GetDataAt(size_t index,const TypeId & id,void * data,size_t size)343 AnyReturnValue GetDataAt(size_t index, const TypeId& id, void* data, size_t size) const override
344 {
345 if (IsValidItemArgs(id, data, size) && index < GetSize()) {
346 *static_cast<ItemType*>(data) = value_[index];
347 return AnyReturn::SUCCESS;
348 }
349 return AnyReturn::INVALID_ARGUMENT;
350 }
SetDataAt(size_t index,const TypeId & id,const void * data,size_t size)351 AnyReturnValue SetDataAt(size_t index, const TypeId& id, const void* data, size_t size) override
352 {
353 if (IsValidItemArgs(id, data, size) && index < GetSize()) {
354 value_[index] = *static_cast<const ItemType*>(data);
355 return AnyReturn::SUCCESS;
356 }
357 return AnyReturn::INVALID_ARGUMENT;
358 }
SetAnyAt(IArrayAny::IndexType index,const IAny & value)359 AnyReturnValue SetAnyAt(IArrayAny::IndexType index, const IAny& value) override
360 {
361 ItemType v;
362 if (value.GetData(ITEM_TYPE_ID, &v, ITEM_SIZE)) {
363 return SetDataAt(index, ITEM_TYPE_ID, &v, ITEM_SIZE);
364 }
365 return AnyReturn::INVALID_ARGUMENT;
366 }
GetAnyAt(IArrayAny::IndexType index,IAny & value)367 AnyReturnValue GetAnyAt(IArrayAny::IndexType index, IAny& value) const override
368 {
369 ItemType v;
370 if (GetDataAt(index, ITEM_TYPE_ID, &v, ITEM_SIZE)) {
371 return value.SetData(ITEM_TYPE_ID, &v, ITEM_SIZE);
372 }
373 return AnyReturn::INVALID_ARGUMENT;
374 }
InsertAnyAt(IArrayAny::IndexType index,const IAny & value)375 AnyReturnValue InsertAnyAt(IArrayAny::IndexType index, const IAny& value) override
376 {
377 ItemType v;
378 if (value.GetData(ITEM_TYPE_ID, &v, ITEM_SIZE)) {
379 index = index < value_.size() ? index : value_.size();
380 value_.insert(value_.begin() + index, v);
381 return AnyReturn::SUCCESS;
382 }
383 return AnyReturn::INVALID_ARGUMENT;
384 }
RemoveAt(IArrayAny::IndexType index)385 AnyReturnValue RemoveAt(IArrayAny::IndexType index) override
386 {
387 if (index < value_.size()) {
388 value_.erase(value_.begin() + index);
389 return AnyReturn::SUCCESS;
390 }
391 return AnyReturn::INVALID_ARGUMENT;
392 }
RemoveAll()393 void RemoveAll() override
394 {
395 value_.clear();
396 }
397
GetSize()398 IArrayAny::IndexType GetSize() const noexcept override
399 {
400 return value_.size();
401 }
402 IAny::Ptr Clone(const AnyCloneOptions& options) const override;
Clone(bool withValue)403 IAny::Ptr Clone(bool withValue) const
404 {
405 return Clone({ withValue ? CloneValueType::COPY_VALUE : CloneValueType::DEFAULT_VALUE });
406 }
407
InternalGetValue()408 const ArrayType& InternalGetValue() const override
409 {
410 return value_;
411 }
412
PushBack(ItemType item)413 void PushBack(ItemType item)
414 {
415 value_.push_back(BASE_NS::move(item));
416 }
417
418 private:
InternalSetValue(const ArrayType & value)419 AnyReturnValue InternalSetValue(const ArrayType& value) override
420 {
421 if (!Compare::Equal(value, value_)) {
422 value_ = value;
423 return AnyReturn::SUCCESS;
424 }
425 return AnyReturn::NOTHING_TO_DO;
426 }
427
IsValidItemArgs(const TypeId & uid,const void * data,size_t size)428 static constexpr bool IsValidItemArgs(const TypeId& uid, const void* data, size_t size)
429 {
430 return data && ITEM_SIZE == size && uid == Super::ITEM_TYPE_ID;
431 }
432
433 private:
434 ArrayType value_;
435 };
436
437 template<class Type, class Compare>
Clone(const AnyCloneOptions & options)438 IAny::Ptr Any<Type, Compare>::Clone(const AnyCloneOptions& options) const
439 {
440 if (options.role == TypeIdRole::ARRAY) {
441 return IAny::Ptr(new ArrayAny<Type>());
442 }
443 return IAny::Ptr(new Any { options.value == CloneValueType::COPY_VALUE ? value_ : Type {} });
444 }
445
446 template<class Type, class Compare>
Clone(const AnyCloneOptions & options)447 IAny::Ptr ArrayAny<Type, Compare>::Clone(const AnyCloneOptions& options) const
448 {
449 if (options.role == TypeIdRole::ITEM) {
450 return IAny::Ptr(new Any<Type>());
451 }
452 return IAny::Ptr(new ArrayAny { options.value == CloneValueType::COPY_VALUE ? value_ : ArrayType {} });
453 }
454
455 template<class Type, class Compare = DefaultCompare<Type>>
456 static IAny::Ptr ConstructAny(Type v = {})
457 {
458 return IAny::Ptr { new Any<Type, Compare>(BASE_NS::move(v)) };
459 }
460
461 template<class Type, class Compare = DefaultCompare<BASE_NS::vector<Type>>>
462 static IArrayAny::Ptr ConstructArrayAny(BASE_NS::vector<Type> v = {})
463 {
464 return IArrayAny::Ptr { new ArrayAny<Type, Compare>(BASE_NS::move(v)) };
465 }
466
467 META_END_NAMESPACE()
468
469 #endif
470