18bf80f4bSopenharmony_ci/*
28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License.
58bf80f4bSopenharmony_ci * You may obtain a copy of the License at
68bf80f4bSopenharmony_ci *
78bf80f4bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
88bf80f4bSopenharmony_ci *
98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and
138bf80f4bSopenharmony_ci * limitations under the License.
148bf80f4bSopenharmony_ci */
158bf80f4bSopenharmony_ci#include "number.h"
168bf80f4bSopenharmony_ci
178bf80f4bSopenharmony_ci#include <limits>
188bf80f4bSopenharmony_ci
198bf80f4bSopenharmony_ciMETA_BEGIN_NAMESPACE()
208bf80f4bSopenharmony_cinamespace Internal {
218bf80f4bSopenharmony_ci
228bf80f4bSopenharmony_citemplate<typename T>
238bf80f4bSopenharmony_cistruct Type {};
248bf80f4bSopenharmony_ci
258bf80f4bSopenharmony_citemplate<typename T>
268bf80f4bSopenharmony_cistatic Number::VariantType MapToVariant(const T& v)
278bf80f4bSopenharmony_ci{
288bf80f4bSopenharmony_ci    if constexpr (std::numeric_limits<T>::is_integer) {
298bf80f4bSopenharmony_ci        if constexpr (std::numeric_limits<T>::is_signed) {
308bf80f4bSopenharmony_ci            return Number::VariantType(static_cast<int64_t>(v));
318bf80f4bSopenharmony_ci        }
328bf80f4bSopenharmony_ci        return Number::VariantType(static_cast<uint64_t>(v));
338bf80f4bSopenharmony_ci    }
348bf80f4bSopenharmony_ci    return Number::VariantType(static_cast<float>(v));
358bf80f4bSopenharmony_ci}
368bf80f4bSopenharmony_ci
378bf80f4bSopenharmony_cistruct CompType {
388bf80f4bSopenharmony_ci    template<typename T>
398bf80f4bSopenharmony_ci    constexpr CompType(Type<T>)
408bf80f4bSopenharmony_ci        : uid(UidFromType<T>()), size(sizeof(T)), load([](const void* data) {
418bf80f4bSopenharmony_ci              T v = *static_cast<const T*>(data);
428bf80f4bSopenharmony_ci              return MapToVariant(v);
438bf80f4bSopenharmony_ci        }),
448bf80f4bSopenharmony_ci        save([](Number::VariantType var, void* data) {
458bf80f4bSopenharmony_ci            T v {};
468bf80f4bSopenharmony_ci            std::visit([&](const auto& arg) {
478bf80f4bSopenharmony_ci                v = static_cast<T>(arg);
488bf80f4bSopenharmony_ci            }, var);
498bf80f4bSopenharmony_ci            *static_cast<T*>(data) = v;
508bf80f4bSopenharmony_ci        }),
518bf80f4bSopenharmony_ci        loadAny([](const IAny& any, Number::VariantType& var) {
528bf80f4bSopenharmony_ci            T v {};
538bf80f4bSopenharmony_ci            bool res = any.GetValue(v);
548bf80f4bSopenharmony_ci            if (res) {
558bf80f4bSopenharmony_ci                var = MapToVariant(v);
568bf80f4bSopenharmony_ci            }
578bf80f4bSopenharmony_ci            return res;
588bf80f4bSopenharmony_ci        })
598bf80f4bSopenharmony_ci    {}
608bf80f4bSopenharmony_ci
618bf80f4bSopenharmony_ci    using LoadFunc = Number::VariantType(const void*);
628bf80f4bSopenharmony_ci    using SaveFunc = void(Number::VariantType, void*);
638bf80f4bSopenharmony_ci    using LoadAnyFunc = bool(const IAny&, Number::VariantType&);
648bf80f4bSopenharmony_ci
658bf80f4bSopenharmony_ci    const TypeId uid;
668bf80f4bSopenharmony_ci    const size_t size;
678bf80f4bSopenharmony_ci    LoadFunc* const load;
688bf80f4bSopenharmony_ci    SaveFunc* const save;
698bf80f4bSopenharmony_ci    LoadAnyFunc* const loadAny;
708bf80f4bSopenharmony_ci};
718bf80f4bSopenharmony_ci
728bf80f4bSopenharmony_ciconstexpr CompType COMPATIBLES[] = {
738bf80f4bSopenharmony_ci    Type<float>(),
748bf80f4bSopenharmony_ci    Type<double>(),
758bf80f4bSopenharmony_ci    Type<bool>(),
768bf80f4bSopenharmony_ci    Type<uint8_t>(),
778bf80f4bSopenharmony_ci    Type<uint16_t>(),
788bf80f4bSopenharmony_ci    Type<uint32_t>(),
798bf80f4bSopenharmony_ci    Type<uint64_t>(),
808bf80f4bSopenharmony_ci    Type<int8_t>(),
818bf80f4bSopenharmony_ci    Type<int16_t>(),
828bf80f4bSopenharmony_ci    Type<int32_t>(),
838bf80f4bSopenharmony_ci    Type<int64_t>(),
848bf80f4bSopenharmony_ci};
858bf80f4bSopenharmony_ci
868bf80f4bSopenharmony_cistatic BASE_NS::vector<TypeId> CompatibleTypes()
878bf80f4bSopenharmony_ci{
888bf80f4bSopenharmony_ci    BASE_NS::vector<TypeId> res;
898bf80f4bSopenharmony_ci    for (auto&& v : COMPATIBLES) {
908bf80f4bSopenharmony_ci        res.push_back(v.uid);
918bf80f4bSopenharmony_ci    }
928bf80f4bSopenharmony_ci    return res;
938bf80f4bSopenharmony_ci}
948bf80f4bSopenharmony_ci
958bf80f4bSopenharmony_cistatic const CompType* FindCompatible(const TypeId& uid, size_t size)
968bf80f4bSopenharmony_ci{
978bf80f4bSopenharmony_ci    for (auto&& v : COMPATIBLES) {
988bf80f4bSopenharmony_ci        if (v.uid == uid && v.size == size) {
998bf80f4bSopenharmony_ci            return &v;
1008bf80f4bSopenharmony_ci        }
1018bf80f4bSopenharmony_ci    }
1028bf80f4bSopenharmony_ci    return nullptr;
1038bf80f4bSopenharmony_ci}
1048bf80f4bSopenharmony_ci
1058bf80f4bSopenharmony_cistatic const CompType* FindCompatible(const IAny& any)
1068bf80f4bSopenharmony_ci{
1078bf80f4bSopenharmony_ci    auto anyComps = any.GetCompatibleTypes(CompatibilityDirection::BOTH);
1088bf80f4bSopenharmony_ci    for (auto&& v : COMPATIBLES) {
1098bf80f4bSopenharmony_ci        for (auto&& av : anyComps) {
1108bf80f4bSopenharmony_ci            if (v.uid == av) {
1118bf80f4bSopenharmony_ci                return &v;
1128bf80f4bSopenharmony_ci            }
1138bf80f4bSopenharmony_ci        }
1148bf80f4bSopenharmony_ci    }
1158bf80f4bSopenharmony_ci    return nullptr;
1168bf80f4bSopenharmony_ci}
1178bf80f4bSopenharmony_ci
1188bf80f4bSopenharmony_ciNumber::Number(VariantType v) : value_(v) {}
1198bf80f4bSopenharmony_ciconst BASE_NS::array_view<const TypeId> Number::GetCompatibleTypes(CompatibilityDirection dir) const
1208bf80f4bSopenharmony_ci{
1218bf80f4bSopenharmony_ci    static BASE_NS::vector<TypeId> types = CompatibleTypes();
1228bf80f4bSopenharmony_ci    return types;
1238bf80f4bSopenharmony_ci}
1248bf80f4bSopenharmony_ciAnyReturnValue Number::GetData(const TypeId& uid, void* data, size_t size) const
1258bf80f4bSopenharmony_ci{
1268bf80f4bSopenharmony_ci    if (auto c = FindCompatible(uid, size)) {
1278bf80f4bSopenharmony_ci        c->save(value_, data);
1288bf80f4bSopenharmony_ci        return AnyReturn::SUCCESS;
1298bf80f4bSopenharmony_ci    }
1308bf80f4bSopenharmony_ci    return AnyReturn::INCOMPATIBLE_TYPE;
1318bf80f4bSopenharmony_ci}
1328bf80f4bSopenharmony_ciAnyReturnValue Number::SetData(const TypeId& uid, const void* data, size_t size)
1338bf80f4bSopenharmony_ci{
1348bf80f4bSopenharmony_ci    if (auto c = FindCompatible(uid, size)) {
1358bf80f4bSopenharmony_ci        value_ = c->load(data);
1368bf80f4bSopenharmony_ci        return AnyReturn::SUCCESS;
1378bf80f4bSopenharmony_ci    }
1388bf80f4bSopenharmony_ci    return AnyReturn::INCOMPATIBLE_TYPE;
1398bf80f4bSopenharmony_ci}
1408bf80f4bSopenharmony_ciAnyReturnValue Number::CopyFrom(const IAny& any)
1418bf80f4bSopenharmony_ci{
1428bf80f4bSopenharmony_ci    if (auto c = FindCompatible(any)) {
1438bf80f4bSopenharmony_ci        c->loadAny(any, value_);
1448bf80f4bSopenharmony_ci    }
1458bf80f4bSopenharmony_ci    return AnyReturn::INCOMPATIBLE_TYPE;
1468bf80f4bSopenharmony_ci}
1478bf80f4bSopenharmony_ciIAny::Ptr Number::Clone(const AnyCloneOptions& options) const
1488bf80f4bSopenharmony_ci{
1498bf80f4bSopenharmony_ci    if (options.role == TypeIdRole::ARRAY) {
1508bf80f4bSopenharmony_ci        CORE_LOG_E("Number: cloning into an array not supported.");
1518bf80f4bSopenharmony_ci        return {};
1528bf80f4bSopenharmony_ci    }
1538bf80f4bSopenharmony_ci    return IAny::Ptr(new Number(options.value == CloneValueType::COPY_VALUE ? value_ : VariantType {}));
1548bf80f4bSopenharmony_ci}
1558bf80f4bSopenharmony_ciTypeId Number::GetTypeId(TypeIdRole role) const
1568bf80f4bSopenharmony_ci{
1578bf80f4bSopenharmony_ci    if (role == TypeIdRole::ARRAY) {
1588bf80f4bSopenharmony_ci        return std::visit([&](auto arg) { return ArrayUidFromType<decltype(arg)>(); }, value_);
1598bf80f4bSopenharmony_ci    }
1608bf80f4bSopenharmony_ci    return std::visit([&](auto arg) { return UidFromType<decltype(arg)>(); }, value_);
1618bf80f4bSopenharmony_ci}
1628bf80f4bSopenharmony_ci
1638bf80f4bSopenharmony_ciBASE_NS::string Number::GetTypeIdString() const
1648bf80f4bSopenharmony_ci{
1658bf80f4bSopenharmony_ci    return std::visit([&](auto arg) { return MetaType<decltype(arg)>::name; }, value_);
1668bf80f4bSopenharmony_ci}
1678bf80f4bSopenharmony_ci
1688bf80f4bSopenharmony_ci} // namespace Internal
1698bf80f4bSopenharmony_ciMETA_END_NAMESPACE()
170