• 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 #ifndef META_INTERFACE_DETAIL_BASE_ANY_H
16 #define META_INTERFACE_DETAIL_BASE_ANY_H
17 
18 #include <meta/interface/detail/any_pointer_compatibility.h>
19 #include <meta/interface/interface_helpers.h>
20 #include <meta/interface/intf_any.h>
21 #include <meta/interface/intf_value.h>
22 
23 META_BEGIN_NAMESPACE()
24 
25 constexpr char BUILTIN_ANY_TAG[] = "BuiltAny";
26 constexpr char BUILTIN_ARRAY_ANY_TAG[] = "ArrayAny";
27 
28 template<typename Type>
29 class BaseTypedAny : public IntroduceInterfaces<IAny, IValue> {
30 public:
31     static constexpr TypeId TYPE_ID = UidFromType<Type>();
32     static constexpr bool IS_PTR_TYPE = IsInterfacePtr_v<Type>;
33 
StaticGetClassId()34     static constexpr ObjectId StaticGetClassId()
35     {
36         return MakeUid<Type>(BUILTIN_ANY_TAG);
37     }
StaticGetTypeIdString()38     static constexpr BASE_NS::string_view StaticGetTypeIdString()
39     {
40         return MetaType<Type>::name;
41     }
StaticGetCompatibleTypes(CompatibilityDirection dir)42     static const BASE_NS::array_view<const TypeId> StaticGetCompatibleTypes(CompatibilityDirection dir)
43     {
44         if constexpr (IS_PTR_TYPE) {
45             return AnyPC<Type>::template GetCompatibleTypes<Type>(dir);
46         }
47 
48         static constexpr TypeId uids[] = { TYPE_ID };
49         return uids;
50     }
51 
GetClassId()52     ObjectId GetClassId() const override
53     {
54         return StaticGetClassId();
55     }
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 
183     template<typename NewType>
184     using Rebind = DefaultCompare<NewType>;
185 };
186 
187 /**
188  * @brief Default IAny implementation which supports a single type.
189  */
190 template<typename Type, typename Compare = DefaultCompare<Type>>
191 class Any : public BaseTypedAny<Type> {
192     using Super = BaseTypedAny<Type>;
193 
194 public:
value_(BASE_NS::move (v))195     explicit Any(Type v = {}) : value_(BASE_NS::move(v)) {}
InternalSetValue(const Type & value)196     AnyReturnValue InternalSetValue(const Type& value) override
197     {
198         if (!Compare::Equal(value, value_)) {
199             value_ = value;
200             return AnyReturn::SUCCESS;
201         }
202         return AnyReturn::NOTHING_TO_DO;
203     }
InternalGetValue()204     const Type& InternalGetValue() const override
205     {
206         return value_;
207     }
208     IAny::Ptr Clone(const AnyCloneOptions& options) const override;
Clone(bool withValue)209     IAny::Ptr Clone(bool withValue) const
210     {
211         return Clone({ withValue ? CloneValueType::COPY_VALUE : CloneValueType::DEFAULT_VALUE });
212     }
213 
214     bool operator==(const Any<Type>& other) const noexcept
215     {
216         return (Compare::Equal(other.InternalGetValue(), value_));
217     }
218 
ResetValue()219     AnyReturnValue ResetValue() override
220     {
221         return InternalSetValue({});
222     }
223 
224 private:
225     Type value_;
226 };
227 
228 template<typename Type>
229 class BaseTypedArrayAny : public IntroduceInterfaces<IArrayAny, IValue> {
230 public:
231     static constexpr TypeId VECTOR_TYPE_ID = UidFromType<BASE_NS::vector<Type>>();
232     static constexpr TypeId ARRAY_TYPE_ID = ArrayUidFromType<Type>();
233     static constexpr TypeId ITEM_TYPE_ID = ItemUidFromType<Type>();
234     static constexpr TypeId TYPE_ID = ARRAY_TYPE_ID;
235     using ItemType = Type;
236     using ArrayType = BASE_NS::vector<Type>;
237 
StaticGetClassId()238     static constexpr ObjectId StaticGetClassId()
239     {
240         return MakeUid<Type>(BUILTIN_ARRAY_ANY_TAG);
241     }
242 
StaticGetTypeIdString()243     static constexpr BASE_NS::string_view StaticGetTypeIdString()
244     {
245         return MetaType<ArrayType>::name;
246     }
247 
GetClassId()248     ObjectId GetClassId() const override
249     {
250         return StaticGetClassId();
251     }
252 
GetCompatibleTypes(CompatibilityDirection dir)253     const BASE_NS::array_view<const TypeId> GetCompatibleTypes(CompatibilityDirection dir) const override
254     {
255         static constexpr TypeId uids[] = { ARRAY_TYPE_ID, VECTOR_TYPE_ID };
256         return uids;
257     }
GetItemCompatibleTypes(CompatibilityDirection dir)258     const BASE_NS::array_view<const TypeId> GetItemCompatibleTypes(CompatibilityDirection dir) const override
259     {
260         return BaseTypedAny<Type>::StaticGetCompatibleTypes(dir);
261     }
GetData(const TypeId & id,void * data,size_t size)262     AnyReturnValue GetData(const TypeId& id, void* data, size_t size) const override
263     {
264         if (IsValidVectorArgs(id, data, size)) {
265             *static_cast<ArrayType*>(data) = InternalGetValue();
266             return AnyReturn::SUCCESS;
267         }
268         if (IsValidArrayArgs(id, data)) {
269             auto& value = InternalGetValue();
270             const auto valueSize = value.size() * sizeof(Type); /*NOLINT(bugprone-sizeof-expression)*/
271             if (size >= valueSize) {
272                 BASE_NS::CloneData(data, size, value.data(), valueSize);
273                 return AnyReturn::SUCCESS;
274             }
275         }
276         return AnyReturn::INVALID_ARGUMENT;
277     }
SetData(const TypeId & id,const void * data,size_t size)278     AnyReturnValue SetData(const TypeId& id, const void* data, size_t size) override
279     {
280         if (IsValidVectorArgs(id, data, size)) {
281             return InternalSetValue(*static_cast<const ArrayType*>(data));
282         }
283         if (IsValidArrayArgs(id, data)) {
284             auto p = static_cast<const Type*>(data);
285             return InternalSetValue(
286                 BASE_NS::vector<Type>(p, p + size / sizeof(Type))); /*NOLINT(bugprone-sizeof-expression)*/
287         }
288         return AnyReturn::INVALID_ARGUMENT;
289     }
CopyFrom(const IAny & any)290     AnyReturnValue CopyFrom(const IAny& any) override
291     {
292         if (META_NS::IsCompatible(any, TYPE_ID, CompatibilityDirection::GET)) {
293             ArrayType value;
294             if (any.GetValue(value)) {
295                 return InternalSetValue(value);
296             }
297         }
298         return AnyReturn::FAIL;
299     }
300 
GetTypeId(TypeIdRole role)301     TypeId GetTypeId(TypeIdRole role) const override
302     {
303         if (role == TypeIdRole::ARRAY) {
304             return ARRAY_TYPE_ID;
305         }
306         if (role == TypeIdRole::ITEM) {
307             return ITEM_TYPE_ID;
308         }
309         return TYPE_ID;
310     }
GetTypeId()311     TypeId GetTypeId() const
312     {
313         return TYPE_ID;
314     }
GetTypeIdString()315     BASE_NS::string GetTypeIdString() const override
316     {
317         return BASE_NS::string(StaticGetTypeIdString());
318     }
319     using IAny::SetValue;
SetValue(const IAny & value)320     AnyReturnValue SetValue(const IAny& value) override
321     {
322         return CopyFrom(value);
323     }
324     using IAny::GetValue;
GetValue()325     const IAny& GetValue() const override
326     {
327         return *this;
328     }
IsCompatible(const TypeId & id)329     bool IsCompatible(const TypeId& id) const override
330     {
331         return META_NS::IsCompatible(*this, id);
332     }
333 
334 protected:
335     virtual AnyReturnValue InternalSetValue(const ArrayType& value) = 0;
336     virtual const ArrayType& InternalGetValue() const = 0;
337 
338 private:
IsValidVectorArgs(const TypeId & uid,const void * data,size_t size)339     static constexpr bool IsValidVectorArgs(const TypeId& uid, const void* data, size_t size)
340     {
341         return data && sizeof(ArrayType) == size && uid == VECTOR_TYPE_ID;
342     }
IsValidArrayArgs(const TypeId & uid,const void * data)343     static constexpr bool IsValidArrayArgs(const TypeId& uid, const void* data)
344     {
345         return data && uid == ARRAY_TYPE_ID;
346     }
347 };
348 
349 /**
350  * @brief Default IArrayAny implementation which supports a single type.
351  */
352 template<typename Type, typename Compare = DefaultCompare<BASE_NS::vector<Type>>>
353 class ArrayAny : public BaseTypedArrayAny<Type> {
354     using Super = BaseTypedArrayAny<Type>;
355 
356 public:
357     using ArrayType = typename Super::ArrayType;
358     using ItemType = typename Super::ItemType;
359     using Super::ITEM_TYPE_ID;
360     static constexpr auto ITEM_SIZE = sizeof(ItemType); /*NOLINT(bugprone-sizeof-expression)*/
361 
362 public:
value_(BASE_NS::move (v))363     explicit constexpr ArrayAny(ArrayType v = {}) : value_(BASE_NS::move(v)) {}
ArrayAny(const BASE_NS::array_view<const Type> & v)364     explicit constexpr ArrayAny(const BASE_NS::array_view<const Type>& v) : value_(v.begin(), v.end()) {}
365 #ifdef BASE_VECTOR_HAS_INITIALIZE_LIST
ArrayAny(std::initializer_list<Type> v)366     constexpr ArrayAny(std::initializer_list<Type> v) : value_(ArrayType(v)) {}
367 #endif
368     // todo: support same conversions as single value any
GetDataAt(size_t index,const TypeId & id,void * data,size_t size)369     AnyReturnValue GetDataAt(size_t index, const TypeId& id, void* data, size_t size) const override
370     {
371         if (IsValidItemArgs(id, data, size) && index < GetSize()) {
372             *static_cast<ItemType*>(data) = value_[index];
373             return AnyReturn::SUCCESS;
374         }
375         return AnyReturn::INVALID_ARGUMENT;
376     }
377     // todo: support same conversions as single value any
SetDataAt(size_t index,const TypeId & id,const void * data,size_t size)378     AnyReturnValue SetDataAt(size_t index, const TypeId& id, const void* data, size_t size) override
379     {
380         if (IsValidItemArgs(id, data, size) && index < GetSize()) {
381             value_[index] = *static_cast<const ItemType*>(data);
382             return AnyReturn::SUCCESS;
383         }
384         return AnyReturn::INVALID_ARGUMENT;
385     }
SetAnyAt(IArrayAny::IndexType index,const IAny & value)386     AnyReturnValue SetAnyAt(IArrayAny::IndexType index, const IAny& value) override
387     {
388         ItemType v;
389         if (value.GetData(ITEM_TYPE_ID, &v, ITEM_SIZE)) {
390             return SetDataAt(index, ITEM_TYPE_ID, &v, ITEM_SIZE);
391         }
392         return AnyReturn::INVALID_ARGUMENT;
393     }
GetAnyAt(IArrayAny::IndexType index,IAny & value)394     AnyReturnValue GetAnyAt(IArrayAny::IndexType index, IAny& value) const override
395     {
396         ItemType v;
397         if (GetDataAt(index, ITEM_TYPE_ID, &v, ITEM_SIZE)) {
398             return value.SetData(ITEM_TYPE_ID, &v, ITEM_SIZE);
399         }
400         return AnyReturn::INVALID_ARGUMENT;
401     }
InsertAnyAt(IArrayAny::IndexType index,const IAny & value)402     AnyReturnValue InsertAnyAt(IArrayAny::IndexType index, const IAny& value) override
403     {
404         ItemType v;
405         if (value.GetData(ITEM_TYPE_ID, &v, ITEM_SIZE)) {
406             index = index < value_.size() ? index : value_.size();
407             value_.insert(value_.begin() + index, v);
408             return AnyReturn::SUCCESS;
409         }
410         return AnyReturn::INVALID_ARGUMENT;
411     }
RemoveAt(IArrayAny::IndexType index)412     AnyReturnValue RemoveAt(IArrayAny::IndexType index) override
413     {
414         if (index < value_.size()) {
415             value_.erase(value_.begin() + index);
416             return AnyReturn::SUCCESS;
417         }
418         return AnyReturn::INVALID_ARGUMENT;
419     }
RemoveAll()420     void RemoveAll() override
421     {
422         value_.clear();
423     }
424 
GetSize()425     IArrayAny::IndexType GetSize() const noexcept override
426     {
427         return value_.size();
428     }
429     IAny::Ptr Clone(const AnyCloneOptions& options) const override;
Clone(bool withValue)430     IAny::Ptr Clone(bool withValue) const
431     {
432         return Clone({ withValue ? CloneValueType::COPY_VALUE : CloneValueType::DEFAULT_VALUE });
433     }
434 
InternalGetValue()435     const ArrayType& InternalGetValue() const override
436     {
437         return value_;
438     }
439 
PushBack(ItemType item)440     void PushBack(ItemType item)
441     {
442         value_.push_back(BASE_NS::move(item));
443     }
444 
ResetValue()445     AnyReturnValue ResetValue() override
446     {
447         return InternalSetValue({});
448     }
449 
450 private:
InternalSetValue(const ArrayType & value)451     AnyReturnValue InternalSetValue(const ArrayType& value) override
452     {
453         if (!Compare::Equal(value, value_)) {
454             value_ = value;
455             return AnyReturn::SUCCESS;
456         }
457         return AnyReturn::NOTHING_TO_DO;
458     }
459 
IsValidItemArgs(const TypeId & uid,const void * data,size_t size)460     static constexpr bool IsValidItemArgs(const TypeId& uid, const void* data, size_t size)
461     {
462         return data && ITEM_SIZE == size && uid == Super::ITEM_TYPE_ID;
463     }
464 
465 protected:
466     ArrayType value_;
467 };
468 
469 template<class Type, class Compare>
Clone(const AnyCloneOptions & options)470 IAny::Ptr Any<Type, Compare>::Clone(const AnyCloneOptions& options) const
471 {
472     if (options.role == TypeIdRole::ARRAY) {
473         return IAny::Ptr(new ArrayAny<Type, typename Compare::template Rebind<BASE_NS::vector<Type>>>());
474     }
475     return IAny::Ptr(new Any { options.value == CloneValueType::COPY_VALUE ? value_ : Type {} });
476 }
477 
478 template<class Type, class Compare>
Clone(const AnyCloneOptions & options)479 IAny::Ptr ArrayAny<Type, Compare>::Clone(const AnyCloneOptions& options) const
480 {
481     if (options.role == TypeIdRole::ITEM) {
482         return IAny::Ptr(new Any<Type, typename Compare::template Rebind<Type>>());
483     }
484     return IAny::Ptr(new ArrayAny { options.value == CloneValueType::COPY_VALUE ? value_ : ArrayType {} });
485 }
486 
487 META_END_NAMESPACE()
488 
489 #endif
490