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/interface/detail/any.h>
22 #include <meta/interface/engine/intf_engine_value.h>
23 #include <meta/interface/interface_helpers.h>
24 
META_BEGIN_NAMESPACE()25 META_BEGIN_NAMESPACE()
26 
27 template<typename Type, typename AnyType, typename AccessType = Type>
28 class EngineInternalValueAccessImpl : public IntroduceInterfaces<IEngineInternalValueAccess> {
29 public:
30     IAny::Ptr CreateAny() const override
31     {
32         return IAny::Ptr(new AnyType);
33     }
34     bool IsCompatible(const CORE_NS::PropertyTypeDecl& type) const override
35     {
36         return MetaType<Type>::coreType == type;
37     }
38     AnyReturnValue SyncToEngine(const IAny& value, const EnginePropertyParams& params) const override
39     {
40         CORE_NS::ScopedHandle<Type> guard { params.handle };
41         return guard ? value.GetData(UidFromType<AccessType>(), (void*)((uintptr_t) & *guard + params.Offset()),
42                            sizeof(Type)) /*NOLINT(bugprone-sizeof-expression)*/
43                      : AnyReturn::FAIL;
44     }
45     AnyReturnValue SyncFromEngine(const EnginePropertyParams& params, IAny& out) const override
46     {
47         CORE_NS::ScopedHandle<const Type> guard { params.handle };
48         return guard ? out.SetData(UidFromType<AccessType>(), (const void*)((uintptr_t) & *guard + params.Offset()),
49                            sizeof(Type)) /*NOLINT(bugprone-sizeof-expression)*/
50                      : AnyReturn::FAIL;
51     }
52 };
53 
54 template<typename Type>
55 class EngineInternalValueAccess : public EngineInternalValueAccessImpl<Type, Any<Type>> {};
56 template<typename Type>
57 class EngineInternalValueAccess<BASE_NS::vector<Type>>
58     : public EngineInternalValueAccessImpl<BASE_NS::vector<Type>, ArrayAny<Type>> {};
59 
60 template<typename Type>
61 class EngineInternalArrayValueAccess : public IntroduceInterfaces<IEngineInternalValueAccess> {
62 public:
63     using InternalType = BASE_NS::vector<Type>;
64 
CreateAny()65     IAny::Ptr CreateAny() const override
66     {
67         return IAny::Ptr(new ArrayAny<Type>);
68     }
IsCompatible(const CORE_NS::PropertyTypeDecl & type)69     bool IsCompatible(const CORE_NS::PropertyTypeDecl& type) const override
70     {
71         return MetaType<Type[]>::coreType == type;
72     }
SyncToEngine(const IAny & value,const EnginePropertyParams & params)73     AnyReturnValue SyncToEngine(const IAny& value, const EnginePropertyParams& params) const override
74     {
75         AnyReturnValue res = AnyReturn::FAIL;
76         CORE_NS::ScopedHandle<Type[]> guard { params.handle };
77         if (guard && params.property.metaData.containerMethods) {
78             BASE_NS::vector<Type> vec;
79             res = value.GetData(UidFromType<InternalType>(), &vec, sizeof(InternalType));
80             if (res) {
81                 if (params.property.type.isArray) {
82                     size_t size = params.property.count < vec.size() ? params.property.count : vec.size();
83                     for (size_t i = 0; i != size; ++i) {
84                         ((Type*)((uintptr_t) & *guard + params.Offset()))[i] = vec[i];
85                     }
86                 } else {
87                     auto cont = params.property.metaData.containerMethods;
88                     cont->resize(params.Offset(), vec.size());
89                     for (size_t i = 0; i != vec.size(); ++i) {
90                         *((Type*)cont->get(params.Offset(), i)) = vec[i];
91                     }
92                 }
93             }
94         }
95         return res;
96     }
SyncFromEngine(const EnginePropertyParams & params,IAny & out)97     AnyReturnValue SyncFromEngine(const EnginePropertyParams& params, IAny& out) const override
98     {
99         AnyReturnValue res = AnyReturn::FAIL;
100         CORE_NS::ScopedHandle<const Type[]> guard { params.handle };
101         if (guard && params.property.metaData.containerMethods) {
102             BASE_NS::vector<Type> vec;
103             if (params.property.type.isArray) {
104                 vec.resize(params.property.count);
105                 for (size_t i = 0; i != vec.size(); ++i) {
106                     vec[i] = ((const Type*)((uintptr_t) & *guard + params.Offset()))[i];
107                 }
108             } else {
109                 auto cont = params.property.metaData.containerMethods;
110                 vec.resize(cont->size(params.Offset()));
111                 for (size_t i = 0; i != vec.size(); ++i) {
112                     vec[i] = *((const Type*)cont->get(params.Offset(), i));
113                 }
114             }
115             res = out.SetData(UidFromType<InternalType>(), &vec, sizeof(InternalType));
116         }
117         return res;
118     }
119 };
120 
121 META_END_NAMESPACE()
122 
123 #endif