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