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