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 40 ObjectId GetClassId() const override 41 { 42 return StaticGetClassId(); 43 } 44 45 const BASE_NS::array_view<const TypeId> GetCompatibleTypes(CompatibilityDirection dir) const override 46 { onstexpr(IS_PTR_TYPE)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 } 54 AnyReturnValue GetData(const TypeId& id, void* data, size_t size) const override 55 { 56 if (IsValidGetArgs(id, data, size)) { onstexpr(IS_PTR_TYPE)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 } 71 AnyReturnValue SetData(const TypeId& id, const void* data, size_t size) override 72 { 73 if (IsValidSetArgs(id, data, size)) { onstexpr(IS_PTR_TYPE)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 } 87 AnyReturnValue CopyFrom(const IAny& any) override 88 { onstexpr(IS_PTR_TYPE)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 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() const117 TypeId GetTypeId() const 118 { 119 return TYPE_ID; 120 } 121 BASE_NS::string GetTypeIdString() const override 122 { 123 return MetaType<Type>::name; 124 } 125 using IAny::SetValue; 126 AnyReturnValue SetValue(const IAny& value) override 127 { 128 return CopyFrom(value); 129 } 130 using IAny::GetValue; 131 const IAny& GetValue() const override 132 { 133 return *this; 134 } 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: Any(Type v = {})185 explicit Any(Type v = {}) : value_(BASE_NS::move(v)) {} 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 } 194 const Type& InternalGetValue() const override 195 { 196 return value_; 197 } 198 IAny::Ptr Clone(const AnyCloneOptions& options) const override; Clone(bool withValue) const199 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 228 ObjectId GetClassId() const override 229 { 230 return StaticGetClassId(); 231 } 232 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 } 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 } 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 } 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 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() const287 TypeId GetTypeId() const 288 { 289 return TYPE_ID; 290 } 291 BASE_NS::string GetTypeIdString() const override 292 { 293 return MetaType<ArrayType>::name; 294 } 295 using IAny::SetValue; 296 AnyReturnValue SetValue(const IAny& value) override 297 { 298 return CopyFrom(value); 299 } 300 using IAny::GetValue; 301 const IAny& GetValue() const override 302 { 303 return *this; 304 } 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: ArrayAny(ArrayType v = {})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 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 } 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 } 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 } 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 } 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 } 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 } 393 void RemoveAll() override 394 { 395 value_.clear(); 396 } 397 398 IArrayAny::IndexType GetSize() const noexcept override 399 { 400 return value_.size(); 401 } 402 IAny::Ptr Clone(const AnyCloneOptions& options) const override; 403 IAny::Ptr Clone(bool withValue) const 404 { 405 return Clone({ withValue ? CloneValueType::COPY_VALUE : CloneValueType::DEFAULT_VALUE }); 406 } 407 408 const ArrayType& InternalGetValue() const override 409 { 410 return value_; 411 } 412 413 void PushBack(ItemType item) 414 { 415 value_.push_back(BASE_NS::move(item)); 416 } 417 418 private: 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 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> 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> 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