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_ARRAY_PROPERTY_H 17 #define META_INTERFACE_DETAIL_ARRAY_PROPERTY_H 18 19 #include <meta/interface/detail/any.h> 20 #include <meta/interface/detail/property.h> 21 22 META_BEGIN_NAMESPACE() 23 24 template<typename Base> 25 class ConstTypelessArrayPropertyInterfaceImpl : public Base { 26 public: 27 using IndexType = IArrayAny::IndexType; 28 29 template<typename Prop> ConstTypelessArrayPropertyInterfaceImpl(Prop* p)30 explicit ConstTypelessArrayPropertyInterfaceImpl(Prop* p) : Base(p) 31 {} 32 GetSize() const33 IndexType GetSize() const 34 { 35 if (auto arr = interface_cast<IArrayAny>(&this->GetValueAny())) { 36 return arr->GetSize(); 37 } 38 return {}; 39 } GetAnyAt(IndexType index, IAny& any) const40 AnyReturnValue GetAnyAt(IndexType index, IAny& any) const 41 { 42 if (auto arr = interface_cast<IArrayAny>(&this->GetValueAny())) { 43 return arr->GetAnyAt(index, any); 44 } 45 return AnyReturn::INCOMPATIBLE_TYPE; 46 } 47 }; 48 49 using ConstTypelessArrayPropertyInterface = ConstTypelessArrayPropertyInterfaceImpl<ConstTypelessPropertyInterface>; 50 51 class TypelessArrayPropertyInterface : public ConstTypelessArrayPropertyInterfaceImpl<TypelessPropertyInterface> { 52 public: 53 using PropertyType = IProperty*; 54 using IndexType = IArrayAny::IndexType; 55 TypelessArrayPropertyInterface(PropertyType p)56 TypelessArrayPropertyInterface(PropertyType p) 57 : ConstTypelessArrayPropertyInterfaceImpl<TypelessPropertyInterface>(p) 58 {} 59 SetAnyAt(IndexType index, const IAny& v)60 AnyReturnValue SetAnyAt(IndexType index, const IAny& v) 61 { 62 if (auto c = this->GetValueAny().Clone(true)) { 63 if (auto arr = interface_cast<IArrayAny>(c)) { 64 arr->SetAnyAt(index, v); 65 return this->SetValueAny(*arr); 66 } 67 } 68 return AnyReturn::INCOMPATIBLE_TYPE; 69 } AddAny(const IAny& v)70 AnyReturnValue AddAny(const IAny& v) 71 { 72 return InsertAnyAt(-1, v); 73 } InsertAnyAt(IndexType index, const IAny& v)74 AnyReturnValue InsertAnyAt(IndexType index, const IAny& v) 75 { 76 if (auto c = this->GetValueAny().Clone(true)) { 77 if (auto arr = interface_cast<IArrayAny>(c)) { 78 arr->InsertAnyAt(index, v); 79 return this->SetValueAny(*arr); 80 } 81 } 82 return AnyReturn::INCOMPATIBLE_TYPE; 83 } RemoveAt(IndexType index)84 bool RemoveAt(IndexType index) 85 { 86 if (auto c = this->GetValueAny().Clone(true)) { 87 if (auto arr = interface_cast<IArrayAny>(c)) { 88 arr->RemoveAt(index); 89 return this->SetValueAny(*arr); 90 } 91 } 92 return false; 93 } 94 }; 95 96 template<typename Type> 97 using ArrayPropertyBaseType = BASE_NS::conditional_t<BASE_NS::is_const_v<Type>, ConstTypelessArrayPropertyInterface, 98 TypelessArrayPropertyInterface>; 99 100 template<typename Type> 101 class ArrayPropertyInterface : public ArrayPropertyBaseType<Type> { 102 using Super = ArrayPropertyBaseType<Type>; 103 104 public: 105 using ValueType = BASE_NS::remove_const_t<Type>; 106 using PropertyType = typename PropertyBaseType<Type>::PropertyType; 107 using IndexType = IArrayAny::IndexType; 108 ArrayPropertyInterface(PropertyType p)109 explicit ArrayPropertyInterface(PropertyType p) : Super(p) {} 110 GetValueAt(IndexType index) const111 ValueType GetValueAt(IndexType index) const 112 { 113 Any<ValueType> any; 114 if (auto arr = interface_cast<IArrayAny>(&this->GetValueAny())) { 115 arr->GetAnyAt(index, any); 116 } 117 return any.InternalGetValue(); 118 } SetValueAt(IndexType index, const Type& v)119 bool SetValueAt(IndexType index, const Type& v) 120 { 121 BASE_NS::vector<ValueType> vec; 122 if (this->GetValueAny().GetValue(vec)) { 123 if (index < vec.size()) { 124 vec[index] = v; 125 return this->SetValueAny(ArrayAny<ValueType>(BASE_NS::move(vec))); 126 } 127 } 128 return false; 129 } AddValue(const Type& v)130 bool AddValue(const Type& v) 131 { 132 return InsertValueAt(-1, v); 133 } InsertValueAt(IndexType index, const Type& v)134 bool InsertValueAt(IndexType index, const Type& v) 135 { 136 BASE_NS::vector<ValueType> vec; 137 if (this->GetValueAny().GetValue(vec)) { 138 index = index < vec.size() ? index : vec.size(); 139 vec.insert(vec.begin() + index, v); 140 return this->SetValueAny(ArrayAny<ValueType>(BASE_NS::move(vec))); 141 } 142 return false; 143 } GetDefaultValue() const144 BASE_NS::vector<ValueType> GetDefaultValue() const 145 { 146 BASE_NS::vector<ValueType> v; 147 this->GetDefaultValueAny().GetValue(v); 148 return v; 149 } 150 SetDefaultValue(BASE_NS::array_view<const ValueType> value)151 AnyReturnValue SetDefaultValue(BASE_NS::array_view<const ValueType> value) 152 { 153 return this->SetDefaultValueAny(ArrayAny<ValueType>(value)); 154 } 155 156 template<typename T, typename = BASE_NS::enable_if_t<BASE_NS::is_same_v<T, ValueType>>> SetDefaultValue(BASE_NS::vector<T> value)157 AnyReturnValue SetDefaultValue(BASE_NS::vector<T> value) 158 { 159 return this->SetDefaultValueAny(ArrayAny<ValueType>(BASE_NS::move(value))); 160 } 161 SetDefaultValue(BASE_NS::vector<ValueType> value, bool resetToDefault)162 AnyReturnValue SetDefaultValue(BASE_NS::vector<ValueType> value, bool resetToDefault) 163 { 164 auto ret = this->SetDefaultValueAny(ArrayAny<ValueType>(BASE_NS::move(value))); 165 if (resetToDefault && ret) { 166 this->ResetValue(); 167 } 168 return ret; 169 } 170 GetValue() const171 BASE_NS::vector<ValueType> GetValue() const 172 { 173 BASE_NS::vector<ValueType> v {}; 174 this->GetValueAny().GetValue(v); 175 return v; 176 } 177 SetValue(BASE_NS::array_view<const ValueType> value)178 AnyReturnValue SetValue(BASE_NS::array_view<const ValueType> value) 179 { 180 return this->SetValueAny(ArrayAny<ValueType>(value)); 181 } 182 183 template<typename T, typename = BASE_NS::enable_if_t<BASE_NS::is_same_v<T, ValueType>>> SetValue(BASE_NS::vector<T> value)184 AnyReturnValue SetValue(BASE_NS::vector<T> value) 185 { 186 return this->SetValueAny(ArrayAny<ValueType>(BASE_NS::move(value))); 187 } 188 FindFirstValueOf(const Type& v) const189 IndexType FindFirstValueOf(const Type& v) const 190 { 191 for (IndexType i = 0; i != this->GetSize(); ++i) { 192 if (GetValueAt(i) == v) { 193 return i; 194 } 195 } 196 return -1; 197 } 198 }; 199 200 template<typename Type> 201 class TypedArrayPropertyLock final : public ArrayPropertyInterface<Type> { 202 using PropertyType = typename ArrayPropertyInterface<Type>::PropertyType; 203 using IT = ArrayPropertyInterface<Type>; 204 using InterfaceType = BASE_NS::conditional_t<BASE_NS::is_const_v<Type>, const IT*, IT*>; 205 206 META_NO_COPY_MOVE(TypedArrayPropertyLock) 207 208 public: TypedArrayPropertyLock(PropertyType p)209 explicit TypedArrayPropertyLock(PropertyType p) : ArrayPropertyInterface<Type>(p) 210 { 211 if (auto i = interface_cast<ILockable>(p)) { 212 i->Lock(); 213 } 214 } ~TypedArrayPropertyLock()215 ~TypedArrayPropertyLock() 216 { 217 if (auto i = interface_cast<ILockable>(this->GetProperty())) { 218 i->Unlock(); 219 } 220 } 221 operator ->() const222 InterfaceType operator->() const 223 { 224 return const_cast<TypedArrayPropertyLock*>(this); 225 } 226 }; 227 228 template<typename Property> 229 class ArrayPropertyLock final : public ArrayPropertyBaseType<Property> { 230 using InterfaceType = ArrayPropertyBaseType<Property>*; 231 232 META_NO_COPY_MOVE(ArrayPropertyLock) 233 234 public: ArrayPropertyLock(BASE_NS::shared_ptr<Property> p)235 explicit ArrayPropertyLock(BASE_NS::shared_ptr<Property> p) : ArrayPropertyBaseType<Property>(p.get()) 236 { 237 if (auto i = interface_cast<ILockable>(p)) { 238 i->Lock(); 239 } 240 } ~ArrayPropertyLock()241 ~ArrayPropertyLock() 242 { 243 if (auto i = interface_cast<ILockable>(this->GetProperty())) { 244 i->Unlock(); 245 } 246 } 247 operator ->() const248 InterfaceType operator->() const 249 { 250 return const_cast<ArrayPropertyLock*>(this); 251 } 252 }; 253 254 META_END_NAMESPACE() 255 256 #endif 257