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_EXT_ENGINE_INTERNAL_ACCESS_H
17 #define META_EXT_ENGINE_INTERNAL_ACCESS_H
18
19 #include <core/property/scoped_handle.h>
20
21 #include <meta/ext/engine/core_any.h>
22 #include <meta/ext/engine/core_enum_any.h>
23 #include <meta/interface/detail/any.h>
24 #include <meta/interface/engine/intf_engine_value.h>
25 #include <meta/interface/interface_helpers.h>
26
META_BEGIN_NAMESPACE()27 META_BEGIN_NAMESPACE()
28
29 namespace Internal {
30 template<typename T>
31 struct IsArray {
32 static constexpr const bool VALUE = false;
33 using ItemType = T;
34 };
35
36 template<typename T>
37 struct IsArray<BASE_NS::vector<T>> {
38 static constexpr const bool VALUE = true;
39 using ItemType = T;
40 };
41
42 template<typename Type, typename... CompatType>
43 IAny::Ptr ConstructCoreAny(const CORE_NS::Property& p)
44 {
45 if constexpr (Internal::IsArray<Type>::VALUE) {
46 using ItemType = typename Internal::IsArray<Type>::ItemType;
47 if constexpr ((is_enum_v<Type> || ... || is_enum_v<CompatType>)) {
48 return IAny::Ptr(new ArrayCoreEnumAny<ItemType, StaticCastConv, CompatType...>(p));
49 }
50 return IAny::Ptr(new ArrayCoreAny<ItemType, StaticCastConv, CompatType...>(p));
51 } else {
52 if constexpr ((is_enum_v<Type> || ... || is_enum_v<CompatType>)) {
53 return IAny::Ptr(new CoreEnumAny<Type, StaticCastConv, CompatType...>(p));
54 }
55 return IAny::Ptr(new CoreAny<Type, StaticCastConv, CompatType...>(p));
56 }
57 }
58 } // namespace Internal
59
60 /// Class that encapsulates the reading and writing to the core property and the any type used
61 template<typename Type, typename AccessType = Type>
62 class EngineInternalValueAccess : public IntroduceInterfaces<IEngineInternalValueAccess> {
63 public:
64 IAny::Ptr CreateAny(const CORE_NS::Property& p) const override
65 {
66 if constexpr (BASE_NS::is_same_v<Type, AccessType>) {
67 return Internal::ConstructCoreAny<AccessType>(p);
68 } else {
69 return Internal::ConstructCoreAny<AccessType, Type>(p);
70 }
71 }
72 IAny::Ptr CreateSerializableAny() const override
73 {
74 if constexpr (Internal::IsArray<AccessType>::VALUE) {
75 using ItemType = typename Internal::IsArray<AccessType>::ItemType;
76 return IAny::Ptr(new ArrayAnyType<ItemType> {});
77 } else {
78 return IAny::Ptr(new AnyType<AccessType> {});
79 }
80 }
81 bool IsCompatible(const CORE_NS::PropertyTypeDecl& type) const override
82 {
83 return MetaType<Type>::coreType == type;
84 }
85 AnyReturnValue SyncToEngine(const IAny& value, const EnginePropertyParams& params) const override
86 {
87 if (CORE_NS::ScopedHandle<Type> guard { params.handle.Handle() }) {
88 uintptr_t offset = (uintptr_t)(&(*guard)) + params.Offset();
89 auto cont = params.containerMethods;
90 if (cont) {
91 auto arroffset = (uintptr_t)(&(*guard)) + params.arraySubsOffset;
92 if (params.index >= cont->size(arroffset)) {
93 return AnyReturn::FAIL;
94 }
95 offset = uintptr_t(cont->get(arroffset, params.index)) + params.Offset();
96 }
97 return value.GetData(
98 UidFromType<Type>(), (void*)offset, sizeof(Type)); /*NOLINT(bugprone-sizeof-expression)*/
99 }
100 return AnyReturn::FAIL;
101 }
102 AnyReturnValue SyncFromEngine(const EnginePropertyParams& params, IAny& out) const override
103 {
104 if (CORE_NS::ScopedHandle<const Type> guard { params.handle.Handle() }) {
105 uintptr_t offset = (uintptr_t)(&(*guard)) + params.Offset();
106 auto cont = params.containerMethods;
107 if (cont) {
108 auto arroffset = (uintptr_t)(&(*guard)) + params.arraySubsOffset;
109 if (params.index >= cont->size(arroffset)) {
110 return AnyReturn::FAIL;
111 }
112 offset = uintptr_t(cont->get(arroffset, params.index)) + params.Offset();
113 }
114 return out.SetData(
115 UidFromType<Type>(), (const void*)offset, sizeof(Type)); /*NOLINT(bugprone-sizeof-expression)*/
116 }
117 return AnyReturn::FAIL;
118 }
119 };
120
121 /// Class that encapsulates the reading and writing to the core array property and the any type used
122 template<typename Type>
123 class EngineInternalArrayValueAccess : public IntroduceInterfaces<IEngineInternalValueAccess> {
124 public:
125 using InternalType = BASE_NS::vector<Type>;
126
127 IAny::Ptr CreateAny(const CORE_NS::Property& p) const override
128 {
129 return Internal::ConstructCoreAny<InternalType>(p);
130 }
131 IAny::Ptr CreateSerializableAny() const override
132 {
133 return IAny::Ptr(new ArrayAnyType<Type> {});
134 }
135 bool IsCompatible(const CORE_NS::PropertyTypeDecl& type) const override
136 {
137 return MetaType<Type[]>::coreType == type;
138 }
139 AnyReturnValue SyncToEngine(const IAny& value, const EnginePropertyParams& params) const override
140 {
141 AnyReturnValue res = AnyReturn::FAIL;
142 CORE_NS::ScopedHandle<Type[]> guard { params.handle.Handle() };
143 if (guard && params.property.metaData.containerMethods) {
144 BASE_NS::vector<Type> vec;
145 res = value.GetData(UidFromType<InternalType>(), &vec, sizeof(InternalType));
146 if (res) {
147 if (params.property.type.isArray) {
148 size_t size = params.property.count < vec.size() ? params.property.count : vec.size();
149 for (size_t i = 0; i != size; ++i) {
150 ((Type*)((uintptr_t)(&(*guard)) + params.Offset()))[i] = vec[i];
151 }
152 } else {
153 auto cont = params.property.metaData.containerMethods;
154 cont->resize((uintptr_t)(&(*guard)) + params.Offset(), vec.size());
155 for (size_t i = 0; i != vec.size(); ++i) {
156 *((Type*)cont->get((uintptr_t)(&(*guard)) + params.Offset(), i)) = vec[i];
157 }
158 }
159 }
160 }
161 return res;
162 }
163 AnyReturnValue SyncFromEngine(const EnginePropertyParams& params, IAny& out) const override
164 {
165 AnyReturnValue res = AnyReturn::FAIL;
166 CORE_NS::ScopedHandle<const Type[]> guard { params.handle.Handle() };
167 if (guard && params.property.metaData.containerMethods) {
168 BASE_NS::vector<Type> vec;
169 if (params.property.type.isArray) {
170 vec.resize(params.property.count);
171 for (size_t i = 0; i != vec.size(); ++i) {
172 vec[i] = ((const Type*)((uintptr_t)(&(*guard)) + params.Offset()))[i];
173 }
174 } else {
175 auto cont = params.property.metaData.containerMethods;
176 vec.resize(cont->size((uintptr_t)(&(*guard)) + params.Offset()));
177 for (size_t i = 0; i != vec.size(); ++i) {
178 vec[i] = *((const Type*)cont->get((uintptr_t)(&(*guard)) + params.Offset(), i));
179 }
180 }
181 res = out.SetData(UidFromType<InternalType>(), &vec, sizeof(InternalType));
182 }
183 return res;
184 }
185 };
186
187 META_END_NAMESPACE()
188
189 #endif
190