• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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