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 #include "number.h"
16
17 #include <limits>
18
19 META_BEGIN_NAMESPACE()
20 namespace Internal {
21
22 template<typename T>
23 struct Type {};
24
25 template<typename T>
MapToVariant(const T & v)26 static Number::VariantType MapToVariant(const T& v)
27 {
28 if constexpr (std::numeric_limits<T>::is_integer) {
29 if constexpr (std::numeric_limits<T>::is_signed) {
30 return Number::VariantType(static_cast<int64_t>(v));
31 }
32 return Number::VariantType(static_cast<uint64_t>(v));
33 }
34 return Number::VariantType(static_cast<float>(v));
35 }
36
37 struct CompType {
38 template<typename T>
CompTypeInternal::CompType39 constexpr CompType(Type<T>)
40 : uid(UidFromType<T>()), size(sizeof(T)), load([](const void* data) {
41 T v = *static_cast<const T*>(data);
42 return MapToVariant(v);
43 }),
__anonfa3506bd0202Internal::CompType44 save([](Number::VariantType var, void* data) {
45 T v {};
46 std::visit([&](const auto& arg) { v = static_cast<T>(arg); }, var);
47 *static_cast<T*>(data) = v;
48 }),
__anonfa3506bd0402Internal::CompType49 loadAny([](const IAny& any, Number::VariantType& var) {
50 T v {};
51 bool res = any.GetValue(v);
52 if (res) {
53 var = MapToVariant(v);
54 }
55 return res;
56 })
57 {}
58
59 using LoadFunc = Number::VariantType(const void*);
60 using SaveFunc = void(Number::VariantType, void*);
61 using LoadAnyFunc = bool(const IAny&, Number::VariantType&);
62
63 const TypeId uid;
64 const size_t size;
65 LoadFunc* const load;
66 SaveFunc* const save;
67 LoadAnyFunc* const loadAny;
68 };
69
70 constexpr CompType COMPATIBLES[] = {
71 Type<float>(),
72 Type<double>(),
73 Type<bool>(),
74 Type<uint8_t>(),
75 Type<uint16_t>(),
76 Type<uint32_t>(),
77 Type<uint64_t>(),
78 Type<int8_t>(),
79 Type<int16_t>(),
80 Type<int32_t>(),
81 Type<int64_t>(),
82 };
83
CompatibleTypes()84 static BASE_NS::vector<TypeId> CompatibleTypes()
85 {
86 BASE_NS::vector<TypeId> res;
87 for (auto&& v : COMPATIBLES) {
88 res.push_back(v.uid);
89 }
90 return res;
91 }
92
FindCompatible(const TypeId & uid,size_t size)93 static const CompType* FindCompatible(const TypeId& uid, size_t size)
94 {
95 for (auto&& v : COMPATIBLES) {
96 if (v.uid == uid && v.size == size) {
97 return &v;
98 }
99 }
100 return nullptr;
101 }
102
FindCompatible(const IAny & any)103 static const CompType* FindCompatible(const IAny& any)
104 {
105 auto anyComps = any.GetCompatibleTypes(CompatibilityDirection::BOTH);
106 for (auto&& v : COMPATIBLES) {
107 for (auto&& av : anyComps) {
108 if (v.uid == av) {
109 return &v;
110 }
111 }
112 }
113 return nullptr;
114 }
115
Number(VariantType v)116 Number::Number(VariantType v) : value_(v) {}
GetCompatibleTypes(CompatibilityDirection dir) const117 const BASE_NS::array_view<const TypeId> Number::GetCompatibleTypes(CompatibilityDirection dir) const
118 {
119 static BASE_NS::vector<TypeId> types = CompatibleTypes();
120 return types;
121 }
GetData(const TypeId & uid,void * data,size_t size) const122 AnyReturnValue Number::GetData(const TypeId& uid, void* data, size_t size) const
123 {
124 if (auto c = FindCompatible(uid, size)) {
125 c->save(value_, data);
126 return AnyReturn::SUCCESS;
127 }
128 return AnyReturn::INCOMPATIBLE_TYPE;
129 }
SetData(const TypeId & uid,const void * data,size_t size)130 AnyReturnValue Number::SetData(const TypeId& uid, const void* data, size_t size)
131 {
132 if (auto c = FindCompatible(uid, size)) {
133 value_ = c->load(data);
134 return AnyReturn::SUCCESS;
135 }
136 return AnyReturn::INCOMPATIBLE_TYPE;
137 }
CopyFrom(const IAny & any)138 AnyReturnValue Number::CopyFrom(const IAny& any)
139 {
140 if (auto c = FindCompatible(any)) {
141 c->loadAny(any, value_);
142 }
143 return AnyReturn::INCOMPATIBLE_TYPE;
144 }
ResetValue()145 AnyReturnValue Number::ResetValue()
146 {
147 value_ = {};
148 return AnyReturn::SUCCESS;
149 }
Clone(const AnyCloneOptions & options) const150 IAny::Ptr Number::Clone(const AnyCloneOptions& options) const
151 {
152 if (options.role == TypeIdRole::ARRAY) {
153 CORE_LOG_E("Number: cloning into an array not supported.");
154 return {};
155 }
156 return IAny::Ptr(new Number(options.value == CloneValueType::COPY_VALUE ? value_ : VariantType {}));
157 }
GetTypeId(TypeIdRole role) const158 TypeId Number::GetTypeId(TypeIdRole role) const
159 {
160 if (role == TypeIdRole::ARRAY) {
161 return std::visit([&](auto arg) { return ArrayUidFromType<decltype(arg)>(); }, value_);
162 }
163 return std::visit([&](auto arg) { return UidFromType<decltype(arg)>(); }, value_);
164 }
165
GetTypeIdString() const166 BASE_NS::string Number::GetTypeIdString() const
167 {
168 return std::visit([&](auto arg) { return MetaType<decltype(arg)>::name; }, value_);
169 }
170
171 } // namespace Internal
172 META_END_NAMESPACE()
173