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