19596a2c1Sopenharmony_ci/*
29596a2c1Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
39596a2c1Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
49596a2c1Sopenharmony_ci * you may not use this file except in compliance with the License.
59596a2c1Sopenharmony_ci * You may obtain a copy of the License at
69596a2c1Sopenharmony_ci *
79596a2c1Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
89596a2c1Sopenharmony_ci *
99596a2c1Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
109596a2c1Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
119596a2c1Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
129596a2c1Sopenharmony_ci * See the License for the specific language governing permissions and
139596a2c1Sopenharmony_ci * limitations under the License.
149596a2c1Sopenharmony_ci */
159596a2c1Sopenharmony_ci#include "locale_config.h"
169596a2c1Sopenharmony_ci
179596a2c1Sopenharmony_ci#include <cctype>
189596a2c1Sopenharmony_ci#include <sstream>
199596a2c1Sopenharmony_ci#include "i18n_hilog.h"
209596a2c1Sopenharmony_ci#include "ohos/init_data.h"
219596a2c1Sopenharmony_ci#include "parameter.h"
229596a2c1Sopenharmony_ci#include "unicode/ucurr.h"
239596a2c1Sopenharmony_ci#include "unicode/uenum.h"
249596a2c1Sopenharmony_ci#include "unicode/utypes.h"
259596a2c1Sopenharmony_ci#include "utils.h"
269596a2c1Sopenharmony_ci#include "number_format.h"
279596a2c1Sopenharmony_ci
289596a2c1Sopenharmony_cinamespace OHOS {
299596a2c1Sopenharmony_cinamespace Global {
309596a2c1Sopenharmony_cinamespace I18n {
319596a2c1Sopenharmony_ciconst char* NumberFormat::DEVICE_TYPE_NAME = "const.product.devicetype";
329596a2c1Sopenharmony_cistd::unordered_map<std::string, std::string> NumberFormat::numToCurrency = {};
339596a2c1Sopenharmony_cibool NumberFormat::icuInitialized = NumberFormat::Init();
349596a2c1Sopenharmony_ci
359596a2c1Sopenharmony_cistd::unordered_map<std::string, UNumberUnitWidth> NumberFormat::unitStyle = {
369596a2c1Sopenharmony_ci    { "long", UNumberUnitWidth::UNUM_UNIT_WIDTH_FULL_NAME },
379596a2c1Sopenharmony_ci    { "short", UNumberUnitWidth::UNUM_UNIT_WIDTH_SHORT },
389596a2c1Sopenharmony_ci    { "narrow", UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW }
399596a2c1Sopenharmony_ci};
409596a2c1Sopenharmony_ci
419596a2c1Sopenharmony_cistd::unordered_map<std::string, UNumberUnitWidth> NumberFormat::currencyStyle = {
429596a2c1Sopenharmony_ci    { "symbol", UNumberUnitWidth::UNUM_UNIT_WIDTH_SHORT },
439596a2c1Sopenharmony_ci    { "code", UNumberUnitWidth::UNUM_UNIT_WIDTH_ISO_CODE },
449596a2c1Sopenharmony_ci    { "name", UNumberUnitWidth::UNUM_UNIT_WIDTH_FULL_NAME },
459596a2c1Sopenharmony_ci    { "narrowSymbol", UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW }
469596a2c1Sopenharmony_ci};
479596a2c1Sopenharmony_ci
489596a2c1Sopenharmony_cistd::unordered_map<std::string, UNumberSignDisplay> NumberFormat::signAutoStyle = {
499596a2c1Sopenharmony_ci    { "auto", UNumberSignDisplay::UNUM_SIGN_AUTO },
509596a2c1Sopenharmony_ci    { "never", UNumberSignDisplay::UNUM_SIGN_NEVER },
519596a2c1Sopenharmony_ci    { "always", UNumberSignDisplay::UNUM_SIGN_ALWAYS },
529596a2c1Sopenharmony_ci    { "exceptZero", UNumberSignDisplay::UNUM_SIGN_EXCEPT_ZERO }
539596a2c1Sopenharmony_ci};
549596a2c1Sopenharmony_ci
559596a2c1Sopenharmony_cistd::unordered_map<std::string, UNumberSignDisplay> NumberFormat::signAccountingStyle = {
569596a2c1Sopenharmony_ci    { "auto", UNumberSignDisplay::UNUM_SIGN_ACCOUNTING },
579596a2c1Sopenharmony_ci    { "never", UNumberSignDisplay::UNUM_SIGN_NEVER },
589596a2c1Sopenharmony_ci    { "always", UNumberSignDisplay::UNUM_SIGN_ACCOUNTING_ALWAYS },
599596a2c1Sopenharmony_ci    { "exceptZero", UNumberSignDisplay::UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO }
609596a2c1Sopenharmony_ci};
619596a2c1Sopenharmony_ci
629596a2c1Sopenharmony_cistd::unordered_map<UMeasurementSystem, std::string> NumberFormat::measurementSystem = {
639596a2c1Sopenharmony_ci    { UMeasurementSystem::UMS_SI, "SI" },
649596a2c1Sopenharmony_ci    { UMeasurementSystem::UMS_US, "US" },
659596a2c1Sopenharmony_ci    { UMeasurementSystem::UMS_UK, "UK" },
669596a2c1Sopenharmony_ci};
679596a2c1Sopenharmony_ci
689596a2c1Sopenharmony_cistd::unordered_map<std::string, UNumberUnitWidth> NumberFormat::defaultUnitStyle = {
699596a2c1Sopenharmony_ci    { "tablet", UNumberUnitWidth::UNUM_UNIT_WIDTH_FULL_NAME },
709596a2c1Sopenharmony_ci    { "2in1", UNumberUnitWidth::UNUM_UNIT_WIDTH_FULL_NAME },
719596a2c1Sopenharmony_ci    { "tv", UNumberUnitWidth::UNUM_UNIT_WIDTH_FULL_NAME },
729596a2c1Sopenharmony_ci    { "pc", UNumberUnitWidth::UNUM_UNIT_WIDTH_FULL_NAME },
739596a2c1Sopenharmony_ci    { "wearable", UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW },
749596a2c1Sopenharmony_ci    { "liteWearable", UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW },
759596a2c1Sopenharmony_ci    { "watch", UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW }
769596a2c1Sopenharmony_ci};
779596a2c1Sopenharmony_ci
789596a2c1Sopenharmony_cistd::unordered_map<std::string, UNumberUnitWidth> NumberFormat::defaultCurrencyStyle = {
799596a2c1Sopenharmony_ci    { "wearable", UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW },
809596a2c1Sopenharmony_ci    { "liteWearable", UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW },
819596a2c1Sopenharmony_ci    { "watch", UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW }
829596a2c1Sopenharmony_ci};
839596a2c1Sopenharmony_ci
849596a2c1Sopenharmony_cistd::map<std::string, std::string> NumberFormat::RelativeTimeFormatConfigs = {
859596a2c1Sopenharmony_ci    { "numeric", "auto" }
869596a2c1Sopenharmony_ci};
879596a2c1Sopenharmony_ci
889596a2c1Sopenharmony_ciNumberFormat::NumberFormat(const std::vector<std::string> &localeTags, std::map<std::string, std::string> &configs)
899596a2c1Sopenharmony_ci{
909596a2c1Sopenharmony_ci    SetDefaultStyle();
919596a2c1Sopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
929596a2c1Sopenharmony_ci    std::unique_ptr<icu::LocaleBuilder> builder = nullptr;
939596a2c1Sopenharmony_ci    builder = std::make_unique<icu::LocaleBuilder>();
949596a2c1Sopenharmony_ci    ParseConfigs(configs);
959596a2c1Sopenharmony_ci    for (size_t i = 0; i < localeTags.size(); i++) {
969596a2c1Sopenharmony_ci        std::string curLocale = localeTags[i];
979596a2c1Sopenharmony_ci        locale = icu::Locale::forLanguageTag(icu::StringPiece(curLocale), status);
989596a2c1Sopenharmony_ci        if (U_FAILURE(status)) {
999596a2c1Sopenharmony_ci            status = U_ZERO_ERROR;
1009596a2c1Sopenharmony_ci            continue;
1019596a2c1Sopenharmony_ci        }
1029596a2c1Sopenharmony_ci        if (LocaleInfo::allValidLocales.count(locale.getLanguage()) > 0) {
1039596a2c1Sopenharmony_ci            localeInfo = std::make_unique<LocaleInfo>(curLocale, configs);
1049596a2c1Sopenharmony_ci            CreateRelativeTimeFormat(curLocale);
1059596a2c1Sopenharmony_ci            if (!localeInfo->InitSuccess()) {
1069596a2c1Sopenharmony_ci                continue;
1079596a2c1Sopenharmony_ci            }
1089596a2c1Sopenharmony_ci            locale = localeInfo->GetLocale();
1099596a2c1Sopenharmony_ci            localeBaseName = localeInfo->GetBaseName();
1109596a2c1Sopenharmony_ci            numberFormat = icu::number::NumberFormatter::withLocale(locale);
1119596a2c1Sopenharmony_ci            icu::MeasureUnit::getAvailable(unitArray, MAX_UNIT_NUM, status);
1129596a2c1Sopenharmony_ci            if (!U_SUCCESS(status)) {
1139596a2c1Sopenharmony_ci                status = U_ZERO_ERROR;
1149596a2c1Sopenharmony_ci                continue;
1159596a2c1Sopenharmony_ci            }
1169596a2c1Sopenharmony_ci            createSuccess = true;
1179596a2c1Sopenharmony_ci            break;
1189596a2c1Sopenharmony_ci        }
1199596a2c1Sopenharmony_ci    }
1209596a2c1Sopenharmony_ci    if (!createSuccess) {
1219596a2c1Sopenharmony_ci        std::string systemLocale = LocaleConfig::GetSystemLocale();
1229596a2c1Sopenharmony_ci        localeInfo = std::make_unique<LocaleInfo>(systemLocale, configs);
1239596a2c1Sopenharmony_ci        CreateRelativeTimeFormat(systemLocale);
1249596a2c1Sopenharmony_ci        if (localeInfo->InitSuccess()) {
1259596a2c1Sopenharmony_ci            locale = localeInfo->GetLocale();
1269596a2c1Sopenharmony_ci            localeBaseName = localeInfo->GetBaseName();
1279596a2c1Sopenharmony_ci            numberFormat = icu::number::NumberFormatter::withLocale(locale);
1289596a2c1Sopenharmony_ci            icu::MeasureUnit::getAvailable(unitArray, MAX_UNIT_NUM, status);
1299596a2c1Sopenharmony_ci            if (U_SUCCESS(status)) {
1309596a2c1Sopenharmony_ci                createSuccess = true;
1319596a2c1Sopenharmony_ci            }
1329596a2c1Sopenharmony_ci        }
1339596a2c1Sopenharmony_ci    }
1349596a2c1Sopenharmony_ci    if (createSuccess) {
1359596a2c1Sopenharmony_ci        InitProperties();
1369596a2c1Sopenharmony_ci    }
1379596a2c1Sopenharmony_ci}
1389596a2c1Sopenharmony_ci
1399596a2c1Sopenharmony_ciNumberFormat::~NumberFormat()
1409596a2c1Sopenharmony_ci{
1419596a2c1Sopenharmony_ci}
1429596a2c1Sopenharmony_ci
1439596a2c1Sopenharmony_civoid NumberFormat::CreateRelativeTimeFormat(const std::string& locale)
1449596a2c1Sopenharmony_ci{
1459596a2c1Sopenharmony_ci    if (unitUsage == "elapsed-time-second") {
1469596a2c1Sopenharmony_ci        std::vector<std::string> locales = { locale };
1479596a2c1Sopenharmony_ci        relativeTimeFormat = std::make_unique<RelativeTimeFormat>(locales,
1489596a2c1Sopenharmony_ci            RelativeTimeFormatConfigs);
1499596a2c1Sopenharmony_ci    }
1509596a2c1Sopenharmony_ci}
1519596a2c1Sopenharmony_ci
1529596a2c1Sopenharmony_civoid NumberFormat::InitProperties()
1539596a2c1Sopenharmony_ci{
1549596a2c1Sopenharmony_ci    if (!currency.empty()) {
1559596a2c1Sopenharmony_ci        UErrorCode status = U_ZERO_ERROR;
1569596a2c1Sopenharmony_ci        numberFormat =
1579596a2c1Sopenharmony_ci            numberFormat.unit(icu::CurrencyUnit(icu::UnicodeString(currency.c_str()).getBuffer(), status));
1589596a2c1Sopenharmony_ci        if (currencyDisplay != UNumberUnitWidth::UNUM_UNIT_WIDTH_SHORT) {
1599596a2c1Sopenharmony_ci            numberFormat = numberFormat.unitWidth(currencyDisplay);
1609596a2c1Sopenharmony_ci        }
1619596a2c1Sopenharmony_ci    }
1629596a2c1Sopenharmony_ci    if (!styleString.empty() && styleString == "percent") {
1639596a2c1Sopenharmony_ci    // 2 is the power of ten
1649596a2c1Sopenharmony_ci        numberFormat = numberFormat.unit(icu::NoUnit::percent()).scale(icu::number::Scale::powerOfTen(2)).precision(
1659596a2c1Sopenharmony_ci            icu::number::Precision::fixedFraction(0));
1669596a2c1Sopenharmony_ci    }
1679596a2c1Sopenharmony_ci    if (!styleString.empty() && styleString == "unit") {
1689596a2c1Sopenharmony_ci        for (icu::MeasureUnit curUnit : unitArray) {
1699596a2c1Sopenharmony_ci            if (!strcmp(curUnit.getSubtype(), unit.c_str())) {
1709596a2c1Sopenharmony_ci                numberFormat = numberFormat.unit(curUnit);
1719596a2c1Sopenharmony_ci                unitType = curUnit.getType();
1729596a2c1Sopenharmony_ci            }
1739596a2c1Sopenharmony_ci        }
1749596a2c1Sopenharmony_ci        UErrorCode status = U_ZERO_ERROR;
1759596a2c1Sopenharmony_ci        UMeasurementSystem measSys = ulocdata_getMeasurementSystem(localeBaseName.c_str(), &status);
1769596a2c1Sopenharmony_ci        if (U_SUCCESS(status) && measSys >= 0) {
1779596a2c1Sopenharmony_ci            unitMeasSys = measurementSystem[measSys];
1789596a2c1Sopenharmony_ci        }
1799596a2c1Sopenharmony_ci        numberFormat = numberFormat.unitWidth(unitDisplay);
1809596a2c1Sopenharmony_ci        numberFormat = numberFormat.precision(icu::number::Precision::maxFraction(DEFAULT_FRACTION_DIGITS));
1819596a2c1Sopenharmony_ci    }
1829596a2c1Sopenharmony_ci    if (!useGrouping.empty()) {
1839596a2c1Sopenharmony_ci        numberFormat = numberFormat.grouping((useGrouping == "true") ?
1849596a2c1Sopenharmony_ci            UNumberGroupingStrategy::UNUM_GROUPING_AUTO : UNumberGroupingStrategy::UNUM_GROUPING_OFF);
1859596a2c1Sopenharmony_ci    }
1869596a2c1Sopenharmony_ci    if (!currencySign.empty() || !signDisplayString.empty()) {
1879596a2c1Sopenharmony_ci        numberFormat = numberFormat.sign(signDisplay);
1889596a2c1Sopenharmony_ci    }
1899596a2c1Sopenharmony_ci    if (!notationString.empty()) {
1909596a2c1Sopenharmony_ci        numberFormat = numberFormat.notation(notation);
1919596a2c1Sopenharmony_ci    }
1929596a2c1Sopenharmony_ci    InitDigitsProperties();
1939596a2c1Sopenharmony_ci}
1949596a2c1Sopenharmony_ci
1959596a2c1Sopenharmony_civoid NumberFormat::InitDigitsProperties()
1969596a2c1Sopenharmony_ci{
1979596a2c1Sopenharmony_ci    int32_t status = 0;
1989596a2c1Sopenharmony_ci    if (!maximumSignificantDigits.empty() || !minimumSignificantDigits.empty()) {
1999596a2c1Sopenharmony_ci        int32_t maxSignificantDigits = ConvertString2Int(maximumSignificantDigits, status);
2009596a2c1Sopenharmony_ci        if (status == 0) {
2019596a2c1Sopenharmony_ci            numberFormat = numberFormat.precision(icu::number::Precision::maxSignificantDigits(maxSignificantDigits));
2029596a2c1Sopenharmony_ci        }
2039596a2c1Sopenharmony_ci
2049596a2c1Sopenharmony_ci        status = 0;
2059596a2c1Sopenharmony_ci        int32_t minSignificantDigits = ConvertString2Int(minimumSignificantDigits, status);
2069596a2c1Sopenharmony_ci        if (status == 0) {
2079596a2c1Sopenharmony_ci            numberFormat = numberFormat.precision(icu::number::Precision::minSignificantDigits(minSignificantDigits));
2089596a2c1Sopenharmony_ci        }
2099596a2c1Sopenharmony_ci    } else {
2109596a2c1Sopenharmony_ci        int32_t minIntegerDigits = ConvertString2Int(minimumIntegerDigits, status);
2119596a2c1Sopenharmony_ci        if (status == 0 && minIntegerDigits > 1) {
2129596a2c1Sopenharmony_ci            numberFormat =
2139596a2c1Sopenharmony_ci                numberFormat.integerWidth(icu::number::IntegerWidth::zeroFillTo(minIntegerDigits));
2149596a2c1Sopenharmony_ci        }
2159596a2c1Sopenharmony_ci
2169596a2c1Sopenharmony_ci        int32_t minFdStatus = 0;
2179596a2c1Sopenharmony_ci        int32_t minFractionDigits = ConvertString2Int(minimumFractionDigits, minFdStatus);
2189596a2c1Sopenharmony_ci        int32_t maxFdStatus = 0;
2199596a2c1Sopenharmony_ci        int32_t maxFractionDigits = ConvertString2Int(maximumFractionDigits, maxFdStatus);
2209596a2c1Sopenharmony_ci        if (minFdStatus == 0 || maxFdStatus == 0) {
2219596a2c1Sopenharmony_ci            isSetFraction = true;
2229596a2c1Sopenharmony_ci        }
2239596a2c1Sopenharmony_ci        if (minFdStatus == 0 && maxFdStatus != 0) {
2249596a2c1Sopenharmony_ci            numberFormat =
2259596a2c1Sopenharmony_ci                numberFormat.precision(icu::number::Precision::minFraction(minFractionDigits));
2269596a2c1Sopenharmony_ci        } else if (minFdStatus != 0 && maxFdStatus == 0) {
2279596a2c1Sopenharmony_ci            numberFormat =
2289596a2c1Sopenharmony_ci                numberFormat.precision(icu::number::Precision::maxFraction(maxFractionDigits));
2299596a2c1Sopenharmony_ci        } else if (minFdStatus == 0 && maxFdStatus == 0) {
2309596a2c1Sopenharmony_ci            numberFormat =
2319596a2c1Sopenharmony_ci                numberFormat.precision(icu::number::Precision::minMaxFraction(minFractionDigits, maxFractionDigits));
2329596a2c1Sopenharmony_ci        }
2339596a2c1Sopenharmony_ci    }
2349596a2c1Sopenharmony_ci}
2359596a2c1Sopenharmony_ci
2369596a2c1Sopenharmony_civoid NumberFormat::ParseConfigs(std::map<std::string, std::string> &configs)
2379596a2c1Sopenharmony_ci{
2389596a2c1Sopenharmony_ci    if (configs.count("signDisplay") > 0) {
2399596a2c1Sopenharmony_ci        signDisplayString = configs["signDisplay"];
2409596a2c1Sopenharmony_ci    }
2419596a2c1Sopenharmony_ci    if (signAutoStyle.count(signDisplayString) > 0) {
2429596a2c1Sopenharmony_ci        signDisplay = signAutoStyle[signDisplayString];
2439596a2c1Sopenharmony_ci    }
2449596a2c1Sopenharmony_ci    if (configs.count("style") > 0) {
2459596a2c1Sopenharmony_ci        styleString = configs["style"];
2469596a2c1Sopenharmony_ci    }
2479596a2c1Sopenharmony_ci    if (styleString == "unit" && configs.count("unit") > 0) {
2489596a2c1Sopenharmony_ci        unit = configs["unit"];
2499596a2c1Sopenharmony_ci        if (configs.count("unitDisplay") > 0) {
2509596a2c1Sopenharmony_ci            unitDisplayString = configs["unitDisplay"];
2519596a2c1Sopenharmony_ci            if (unitStyle.count(unitDisplayString) > 0) {
2529596a2c1Sopenharmony_ci                unitDisplay = unitStyle[unitDisplayString];
2539596a2c1Sopenharmony_ci            }
2549596a2c1Sopenharmony_ci        }
2559596a2c1Sopenharmony_ci        if (configs.count("unitUsage") > 0) {
2569596a2c1Sopenharmony_ci            unitUsage = configs["unitUsage"];
2579596a2c1Sopenharmony_ci        }
2589596a2c1Sopenharmony_ci    }
2599596a2c1Sopenharmony_ci    if (styleString == "currency" && configs.count("currency") > 0) {
2609596a2c1Sopenharmony_ci        currency = GetCurrencyFromConfig(configs["currency"]);
2619596a2c1Sopenharmony_ci        if (configs.count("currencySign") > 0) {
2629596a2c1Sopenharmony_ci            currencySign = configs["currencySign"];
2639596a2c1Sopenharmony_ci        }
2649596a2c1Sopenharmony_ci        if (currencySign.compare("accounting") == 0 && signAccountingStyle.count(signDisplayString) > 0) {
2659596a2c1Sopenharmony_ci            signDisplay = signAccountingStyle[signDisplayString];
2669596a2c1Sopenharmony_ci        }
2679596a2c1Sopenharmony_ci        if (configs.count("currencyDisplay") > 0 && currencyStyle.count(configs["currencyDisplay"]) > 0) {
2689596a2c1Sopenharmony_ci            currencyDisplayString = configs["currencyDisplay"];
2699596a2c1Sopenharmony_ci            currencyDisplay = currencyStyle[currencyDisplayString];
2709596a2c1Sopenharmony_ci        }
2719596a2c1Sopenharmony_ci    }
2729596a2c1Sopenharmony_ci    ParseDigitsConfigs(configs);
2739596a2c1Sopenharmony_ci}
2749596a2c1Sopenharmony_ci
2759596a2c1Sopenharmony_civoid NumberFormat::ParseDigitsConfigs(std::map<std::string, std::string> &configs)
2769596a2c1Sopenharmony_ci{
2779596a2c1Sopenharmony_ci    if (configs.count("notation") > 0) {
2789596a2c1Sopenharmony_ci        notationString = configs["notation"];
2799596a2c1Sopenharmony_ci        if (notationString == "scientific") {
2809596a2c1Sopenharmony_ci            notation = icu::number::Notation::scientific();
2819596a2c1Sopenharmony_ci        } else if (notationString == "engineering") {
2829596a2c1Sopenharmony_ci            notation = icu::number::Notation::engineering();
2839596a2c1Sopenharmony_ci        }
2849596a2c1Sopenharmony_ci        if (notationString == "compact") {
2859596a2c1Sopenharmony_ci            if (configs.count("compactDisplay") > 0) {
2869596a2c1Sopenharmony_ci                compactDisplay = configs["compactDisplay"];
2879596a2c1Sopenharmony_ci            }
2889596a2c1Sopenharmony_ci            if (compactDisplay == "long") {
2899596a2c1Sopenharmony_ci                notation = icu::number::Notation::compactLong();
2909596a2c1Sopenharmony_ci            } else {
2919596a2c1Sopenharmony_ci                notation = icu::number::Notation::compactShort();
2929596a2c1Sopenharmony_ci            }
2939596a2c1Sopenharmony_ci        }
2949596a2c1Sopenharmony_ci    }
2959596a2c1Sopenharmony_ci    if (configs.count("minimumIntegerDigits") > 0) {
2969596a2c1Sopenharmony_ci        minimumIntegerDigits = configs["minimumIntegerDigits"];
2979596a2c1Sopenharmony_ci    }
2989596a2c1Sopenharmony_ci    if (configs.count("minimumFractionDigits") > 0) {
2999596a2c1Sopenharmony_ci        minimumFractionDigits = configs["minimumFractionDigits"];
3009596a2c1Sopenharmony_ci    }
3019596a2c1Sopenharmony_ci    if (configs.count("maximumFractionDigits") > 0) {
3029596a2c1Sopenharmony_ci        maximumFractionDigits = configs["maximumFractionDigits"];
3039596a2c1Sopenharmony_ci    }
3049596a2c1Sopenharmony_ci    if (configs.count("minimumSignificantDigits") > 0) {
3059596a2c1Sopenharmony_ci        minimumSignificantDigits = configs["minimumSignificantDigits"];
3069596a2c1Sopenharmony_ci    }
3079596a2c1Sopenharmony_ci    if (configs.count("maximumSignificantDigits") > 0) {
3089596a2c1Sopenharmony_ci        maximumSignificantDigits = configs["maximumSignificantDigits"];
3099596a2c1Sopenharmony_ci    }
3109596a2c1Sopenharmony_ci    if (configs.count("numberingSystem") > 0) {
3119596a2c1Sopenharmony_ci        numberingSystem = configs["numberingSystem"];
3129596a2c1Sopenharmony_ci    }
3139596a2c1Sopenharmony_ci    if (configs.count("useGrouping") > 0) {
3149596a2c1Sopenharmony_ci        useGrouping = configs["useGrouping"];
3159596a2c1Sopenharmony_ci    }
3169596a2c1Sopenharmony_ci    if (configs.count("localeMatcher") > 0) {
3179596a2c1Sopenharmony_ci        localeMatcher = configs["localeMatcher"];
3189596a2c1Sopenharmony_ci    }
3199596a2c1Sopenharmony_ci}
3209596a2c1Sopenharmony_ci
3219596a2c1Sopenharmony_civoid NumberFormat::SetUnit(std::string &preferredUnit)
3229596a2c1Sopenharmony_ci{
3239596a2c1Sopenharmony_ci    if (preferredUnit.empty()) {
3249596a2c1Sopenharmony_ci        return;
3259596a2c1Sopenharmony_ci    }
3269596a2c1Sopenharmony_ci    for (icu::MeasureUnit curUnit : unitArray) {
3279596a2c1Sopenharmony_ci        if (!strcmp(curUnit.getSubtype(), preferredUnit.c_str())) {
3289596a2c1Sopenharmony_ci            numberFormat = numberFormat.unit(curUnit);
3299596a2c1Sopenharmony_ci        }
3309596a2c1Sopenharmony_ci    }
3319596a2c1Sopenharmony_ci}
3329596a2c1Sopenharmony_ci
3339596a2c1Sopenharmony_cistd::string NumberFormat::Format(double number)
3349596a2c1Sopenharmony_ci{
3359596a2c1Sopenharmony_ci    if (!createSuccess) {
3369596a2c1Sopenharmony_ci        return PseudoLocalizationProcessor("");
3379596a2c1Sopenharmony_ci    }
3389596a2c1Sopenharmony_ci    double finalNumber = number;
3399596a2c1Sopenharmony_ci    std::string finalUnit = unit;
3409596a2c1Sopenharmony_ci    if ((unitUsage == "size-file-byte" || unitUsage == "size-shortfile-byte") && ConvertByte(finalNumber, finalUnit)) {
3419596a2c1Sopenharmony_ci        SetUnit(finalUnit);
3429596a2c1Sopenharmony_ci        SetPrecisionWithByte(finalNumber, finalUnit);
3439596a2c1Sopenharmony_ci    } else if (unitUsage == "elapsed-time-second" && ConvertDate(finalNumber, finalUnit) &&
3449596a2c1Sopenharmony_ci        relativeTimeFormat != nullptr) {
3459596a2c1Sopenharmony_ci        return relativeTimeFormat->Format(finalNumber, finalUnit);
3469596a2c1Sopenharmony_ci    } else if (!unitUsage.empty()) {
3479596a2c1Sopenharmony_ci        std::vector<std::string> preferredUnits;
3489596a2c1Sopenharmony_ci        if (unitUsage == "default") {
3499596a2c1Sopenharmony_ci            GetDefaultPreferredUnit(localeInfo->GetRegion(), unitType, preferredUnits);
3509596a2c1Sopenharmony_ci        } else {
3519596a2c1Sopenharmony_ci            GetPreferredUnit(localeInfo->GetRegion(), unitUsage, preferredUnits);
3529596a2c1Sopenharmony_ci        }
3539596a2c1Sopenharmony_ci        std::map<double, std::string> preferredValuesOverOne;
3549596a2c1Sopenharmony_ci        std::map<double, std::string> preferredValuesUnderOne;
3559596a2c1Sopenharmony_ci        double num = number;
3569596a2c1Sopenharmony_ci        for (size_t i = 0; i < preferredUnits.size(); i++) {
3579596a2c1Sopenharmony_ci            int status = Convert(num, unit, unitMeasSys, preferredUnits[i], unitMeasSys);
3589596a2c1Sopenharmony_ci            if (!status) {
3599596a2c1Sopenharmony_ci                continue;
3609596a2c1Sopenharmony_ci            }
3619596a2c1Sopenharmony_ci            if (num >= 1) {
3629596a2c1Sopenharmony_ci                preferredValuesOverOne.insert(std::make_pair(num, preferredUnits[i]));
3639596a2c1Sopenharmony_ci            } else {
3649596a2c1Sopenharmony_ci                preferredValuesUnderOne.insert(std::make_pair(num, preferredUnits[i]));
3659596a2c1Sopenharmony_ci            }
3669596a2c1Sopenharmony_ci        }
3679596a2c1Sopenharmony_ci        std::string preferredUnit;
3689596a2c1Sopenharmony_ci        if (preferredValuesOverOne.size() > 0) {
3699596a2c1Sopenharmony_ci            finalNumber = preferredValuesOverOne.begin()->first;
3709596a2c1Sopenharmony_ci            preferredUnit = preferredValuesOverOne.begin()->second;
3719596a2c1Sopenharmony_ci        } else if (preferredValuesUnderOne.size() > 0) {
3729596a2c1Sopenharmony_ci            finalNumber = preferredValuesUnderOne.rbegin()->first;
3739596a2c1Sopenharmony_ci            preferredUnit = preferredValuesUnderOne.rbegin()->second;
3749596a2c1Sopenharmony_ci        }
3759596a2c1Sopenharmony_ci        SetUnit(preferredUnit);
3769596a2c1Sopenharmony_ci    }
3779596a2c1Sopenharmony_ci    std::string result;
3789596a2c1Sopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
3799596a2c1Sopenharmony_ci    numberFormat.formatDouble(finalNumber, status).toString(status).toUTF8String(result);
3809596a2c1Sopenharmony_ci    return PseudoLocalizationProcessor(result);
3819596a2c1Sopenharmony_ci}
3829596a2c1Sopenharmony_ci
3839596a2c1Sopenharmony_civoid NumberFormat::GetResolvedOptions(std::map<std::string, std::string> &map)
3849596a2c1Sopenharmony_ci{
3859596a2c1Sopenharmony_ci    map.insert(std::make_pair("locale", localeBaseName));
3869596a2c1Sopenharmony_ci    if (!styleString.empty()) {
3879596a2c1Sopenharmony_ci        map.insert(std::make_pair("style", styleString));
3889596a2c1Sopenharmony_ci    }
3899596a2c1Sopenharmony_ci    if (!currency.empty()) {
3909596a2c1Sopenharmony_ci        map.insert(std::make_pair("currency", currency));
3919596a2c1Sopenharmony_ci    }
3929596a2c1Sopenharmony_ci    if (!currencySign.empty()) {
3939596a2c1Sopenharmony_ci        map.insert(std::make_pair("currencySign", currencySign));
3949596a2c1Sopenharmony_ci    }
3959596a2c1Sopenharmony_ci    if (!currencyDisplayString.empty()) {
3969596a2c1Sopenharmony_ci        map.insert(std::make_pair("currencyDisplay", currencyDisplayString));
3979596a2c1Sopenharmony_ci    }
3989596a2c1Sopenharmony_ci    if (!signDisplayString.empty()) {
3999596a2c1Sopenharmony_ci        map.insert(std::make_pair("signDisplay", signDisplayString));
4009596a2c1Sopenharmony_ci    }
4019596a2c1Sopenharmony_ci    if (!compactDisplay.empty()) {
4029596a2c1Sopenharmony_ci        map.insert(std::make_pair("compactDisplay", compactDisplay));
4039596a2c1Sopenharmony_ci    }
4049596a2c1Sopenharmony_ci    if (!unitDisplayString.empty()) {
4059596a2c1Sopenharmony_ci        map.insert(std::make_pair("unitDisplay", unitDisplayString));
4069596a2c1Sopenharmony_ci    }
4079596a2c1Sopenharmony_ci    if (!unitUsage.empty()) {
4089596a2c1Sopenharmony_ci        map.insert(std::make_pair("unitUsage", unitUsage));
4099596a2c1Sopenharmony_ci    }
4109596a2c1Sopenharmony_ci    if (!unit.empty()) {
4119596a2c1Sopenharmony_ci        map.insert(std::make_pair("unit", unit));
4129596a2c1Sopenharmony_ci    }
4139596a2c1Sopenharmony_ci    GetDigitsResolvedOptions(map);
4149596a2c1Sopenharmony_ci}
4159596a2c1Sopenharmony_ci
4169596a2c1Sopenharmony_civoid NumberFormat::GetDigitsResolvedOptions(std::map<std::string, std::string> &map)
4179596a2c1Sopenharmony_ci{
4189596a2c1Sopenharmony_ci    if (!numberingSystem.empty()) {
4199596a2c1Sopenharmony_ci        map.insert(std::make_pair("numberingSystem", numberingSystem));
4209596a2c1Sopenharmony_ci    } else if (!(localeInfo->GetNumberingSystem()).empty()) {
4219596a2c1Sopenharmony_ci        map.insert(std::make_pair("numberingSystem", localeInfo->GetNumberingSystem()));
4229596a2c1Sopenharmony_ci    } else {
4239596a2c1Sopenharmony_ci        UErrorCode status = U_ZERO_ERROR;
4249596a2c1Sopenharmony_ci        auto numSys = std::unique_ptr<icu::NumberingSystem>(icu::NumberingSystem::createInstance(locale, status));
4259596a2c1Sopenharmony_ci        if (U_SUCCESS(status)) {
4269596a2c1Sopenharmony_ci            map.insert(std::make_pair("numberingSystem", numSys->getName()));
4279596a2c1Sopenharmony_ci        }
4289596a2c1Sopenharmony_ci    }
4299596a2c1Sopenharmony_ci    if (!useGrouping.empty()) {
4309596a2c1Sopenharmony_ci        map.insert(std::make_pair("useGrouping", useGrouping));
4319596a2c1Sopenharmony_ci    }
4329596a2c1Sopenharmony_ci    if (!minimumIntegerDigits.empty()) {
4339596a2c1Sopenharmony_ci        map.insert(std::make_pair("minimumIntegerDigits", minimumIntegerDigits));
4349596a2c1Sopenharmony_ci    }
4359596a2c1Sopenharmony_ci    if (!minimumFractionDigits.empty()) {
4369596a2c1Sopenharmony_ci        map.insert(std::make_pair("minimumFractionDigits", minimumFractionDigits));
4379596a2c1Sopenharmony_ci    }
4389596a2c1Sopenharmony_ci    if (!maximumFractionDigits.empty()) {
4399596a2c1Sopenharmony_ci        map.insert(std::make_pair("maximumFractionDigits", maximumFractionDigits));
4409596a2c1Sopenharmony_ci    }
4419596a2c1Sopenharmony_ci    if (!minimumSignificantDigits.empty()) {
4429596a2c1Sopenharmony_ci        map.insert(std::make_pair("minimumSignificantDigits", minimumSignificantDigits));
4439596a2c1Sopenharmony_ci    }
4449596a2c1Sopenharmony_ci    if (!maximumSignificantDigits.empty()) {
4459596a2c1Sopenharmony_ci        map.insert(std::make_pair("maximumSignificantDigits", maximumSignificantDigits));
4469596a2c1Sopenharmony_ci    }
4479596a2c1Sopenharmony_ci    if (!localeMatcher.empty()) {
4489596a2c1Sopenharmony_ci        map.insert(std::make_pair("localeMatcher", localeMatcher));
4499596a2c1Sopenharmony_ci    }
4509596a2c1Sopenharmony_ci    if (!notationString.empty()) {
4519596a2c1Sopenharmony_ci        map.insert(std::make_pair("notation", notationString));
4529596a2c1Sopenharmony_ci    }
4539596a2c1Sopenharmony_ci}
4549596a2c1Sopenharmony_ci
4559596a2c1Sopenharmony_civoid NumberFormat::SetPrecisionWithByte(double number, const std::string& finalUnit)
4569596a2c1Sopenharmony_ci{
4579596a2c1Sopenharmony_ci    if (isSetFraction) {
4589596a2c1Sopenharmony_ci        return;
4599596a2c1Sopenharmony_ci    }
4609596a2c1Sopenharmony_ci    int32_t FractionDigits = -1;
4619596a2c1Sopenharmony_ci    // 100 is the threshold between different decimal
4629596a2c1Sopenharmony_ci    if (finalUnit == "byte" || number >= 100) {
4639596a2c1Sopenharmony_ci        FractionDigits = 0;
4649596a2c1Sopenharmony_ci    } else if (number < 1) {
4659596a2c1Sopenharmony_ci        // 2 is the number of significant digits in the decimal
4669596a2c1Sopenharmony_ci        FractionDigits = 2;
4679596a2c1Sopenharmony_ci    // 10 is the threshold between different decimal
4689596a2c1Sopenharmony_ci    } else if (number < 10) {
4699596a2c1Sopenharmony_ci        if (unitUsage == "size-shortfile-byte") {
4709596a2c1Sopenharmony_ci            FractionDigits = 1;
4719596a2c1Sopenharmony_ci        } else {
4729596a2c1Sopenharmony_ci            // 2 is the number of significant digits in the decimal
4739596a2c1Sopenharmony_ci            FractionDigits = 2;
4749596a2c1Sopenharmony_ci        }
4759596a2c1Sopenharmony_ci    } else {
4769596a2c1Sopenharmony_ci        if (unitUsage == "size-shortfile-byte") {
4779596a2c1Sopenharmony_ci            FractionDigits = 0;
4789596a2c1Sopenharmony_ci        } else {
4799596a2c1Sopenharmony_ci            // 2 is the number of significant digits in the decimal
4809596a2c1Sopenharmony_ci            FractionDigits = 2;
4819596a2c1Sopenharmony_ci        }
4829596a2c1Sopenharmony_ci    }
4839596a2c1Sopenharmony_ci    if (FractionDigits != -1) {
4849596a2c1Sopenharmony_ci        numberFormat = numberFormat.precision(icu::number::Precision::minMaxFraction(FractionDigits, FractionDigits));
4859596a2c1Sopenharmony_ci    }
4869596a2c1Sopenharmony_ci}
4879596a2c1Sopenharmony_ci
4889596a2c1Sopenharmony_cistd::string NumberFormat::GetCurrency() const
4899596a2c1Sopenharmony_ci{
4909596a2c1Sopenharmony_ci    return currency;
4919596a2c1Sopenharmony_ci}
4929596a2c1Sopenharmony_ci
4939596a2c1Sopenharmony_cistd::string NumberFormat::GetCurrencySign() const
4949596a2c1Sopenharmony_ci{
4959596a2c1Sopenharmony_ci    return currencySign;
4969596a2c1Sopenharmony_ci}
4979596a2c1Sopenharmony_ci
4989596a2c1Sopenharmony_cistd::string NumberFormat::GetStyle() const
4999596a2c1Sopenharmony_ci{
5009596a2c1Sopenharmony_ci    return styleString;
5019596a2c1Sopenharmony_ci}
5029596a2c1Sopenharmony_ci
5039596a2c1Sopenharmony_cistd::string NumberFormat::GetNumberingSystem() const
5049596a2c1Sopenharmony_ci{
5059596a2c1Sopenharmony_ci    return numberingSystem;
5069596a2c1Sopenharmony_ci}
5079596a2c1Sopenharmony_ci
5089596a2c1Sopenharmony_cistd::string NumberFormat::GetUseGrouping() const
5099596a2c1Sopenharmony_ci{
5109596a2c1Sopenharmony_ci    return useGrouping;
5119596a2c1Sopenharmony_ci}
5129596a2c1Sopenharmony_ci
5139596a2c1Sopenharmony_cistd::string NumberFormat::GetMinimumIntegerDigits() const
5149596a2c1Sopenharmony_ci{
5159596a2c1Sopenharmony_ci    return minimumIntegerDigits;
5169596a2c1Sopenharmony_ci}
5179596a2c1Sopenharmony_ci
5189596a2c1Sopenharmony_cistd::string NumberFormat::GetMinimumFractionDigits() const
5199596a2c1Sopenharmony_ci{
5209596a2c1Sopenharmony_ci    return minimumFractionDigits;
5219596a2c1Sopenharmony_ci}
5229596a2c1Sopenharmony_ci
5239596a2c1Sopenharmony_cistd::string NumberFormat::GetMaximumFractionDigits() const
5249596a2c1Sopenharmony_ci{
5259596a2c1Sopenharmony_ci    return maximumFractionDigits;
5269596a2c1Sopenharmony_ci}
5279596a2c1Sopenharmony_ci
5289596a2c1Sopenharmony_cistd::string NumberFormat::GetMinimumSignificantDigits() const
5299596a2c1Sopenharmony_ci{
5309596a2c1Sopenharmony_ci    return minimumSignificantDigits;
5319596a2c1Sopenharmony_ci}
5329596a2c1Sopenharmony_ci
5339596a2c1Sopenharmony_cistd::string NumberFormat::GetMaximumSignificantDigits() const
5349596a2c1Sopenharmony_ci{
5359596a2c1Sopenharmony_ci    return maximumSignificantDigits;
5369596a2c1Sopenharmony_ci}
5379596a2c1Sopenharmony_ci
5389596a2c1Sopenharmony_cistd::string NumberFormat::GetLocaleMatcher() const
5399596a2c1Sopenharmony_ci{
5409596a2c1Sopenharmony_ci    return localeMatcher;
5419596a2c1Sopenharmony_ci}
5429596a2c1Sopenharmony_ci
5439596a2c1Sopenharmony_cibool NumberFormat::Init()
5449596a2c1Sopenharmony_ci{
5459596a2c1Sopenharmony_ci    SetHwIcuDirectory();
5469596a2c1Sopenharmony_ci    return true;
5479596a2c1Sopenharmony_ci}
5489596a2c1Sopenharmony_ci
5499596a2c1Sopenharmony_civoid NumberFormat::SetDefaultStyle()
5509596a2c1Sopenharmony_ci{
5519596a2c1Sopenharmony_ci    char value[BUFFER_LEN];
5529596a2c1Sopenharmony_ci    int code = GetParameter(DEVICE_TYPE_NAME, "", value, BUFFER_LEN);
5539596a2c1Sopenharmony_ci    if (code > 0) {
5549596a2c1Sopenharmony_ci        std::string deviceType = value;
5559596a2c1Sopenharmony_ci        if (defaultUnitStyle.find(deviceType) != defaultUnitStyle.end()) {
5569596a2c1Sopenharmony_ci            unitDisplay = defaultUnitStyle[deviceType];
5579596a2c1Sopenharmony_ci        }
5589596a2c1Sopenharmony_ci        if (defaultCurrencyStyle.find(deviceType) != defaultCurrencyStyle.end()) {
5599596a2c1Sopenharmony_ci            currencyDisplay = defaultCurrencyStyle[deviceType];
5609596a2c1Sopenharmony_ci        }
5619596a2c1Sopenharmony_ci    }
5629596a2c1Sopenharmony_ci}
5639596a2c1Sopenharmony_ci
5649596a2c1Sopenharmony_cibool NumberFormat::ReadISO4217Ddatas()
5659596a2c1Sopenharmony_ci{
5669596a2c1Sopenharmony_ci    if (numToCurrency.size()) {
5679596a2c1Sopenharmony_ci        return true;
5689596a2c1Sopenharmony_ci    }
5699596a2c1Sopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
5709596a2c1Sopenharmony_ci    const char *currentCurrency;
5719596a2c1Sopenharmony_ci    UEnumeration *currencies = ucurr_openISOCurrencies(UCURR_ALL, &status);
5729596a2c1Sopenharmony_ci    if (U_FAILURE(status)) {
5739596a2c1Sopenharmony_ci        return false;
5749596a2c1Sopenharmony_ci    }
5759596a2c1Sopenharmony_ci
5769596a2c1Sopenharmony_ci    UChar code[CURRENCY_LEN + 1];  // +1 includes the NUL
5779596a2c1Sopenharmony_ci    int32_t length = 0;
5789596a2c1Sopenharmony_ci    while ((currentCurrency = uenum_next(currencies, &length, &status)) != NULL) {
5799596a2c1Sopenharmony_ci        u_charsToUChars(currentCurrency, code, length + 1);  // +1 includes the NUL
5809596a2c1Sopenharmony_ci        const UChar* currencyCode = code;
5819596a2c1Sopenharmony_ci        int32_t numCode = ucurr_getNumericCode(currencyCode);
5829596a2c1Sopenharmony_ci        if (numCode == 0) {
5839596a2c1Sopenharmony_ci            continue;
5849596a2c1Sopenharmony_ci        }
5859596a2c1Sopenharmony_ci        std::stringstream ss;
5869596a2c1Sopenharmony_ci        ss << std::setw(CURRENCY_LEN) << std::setfill('0') << numCode; // fill with '0'
5879596a2c1Sopenharmony_ci        numToCurrency.insert(std::make_pair<std::string, std::string>(ss.str(), currentCurrency));
5889596a2c1Sopenharmony_ci    }
5899596a2c1Sopenharmony_ci    uenum_close(currencies);
5909596a2c1Sopenharmony_ci    return !numToCurrency.empty();
5919596a2c1Sopenharmony_ci}
5929596a2c1Sopenharmony_ci
5939596a2c1Sopenharmony_cistd::string NumberFormat::GetCurrencyFromConfig(const std::string& currency)
5949596a2c1Sopenharmony_ci{
5959596a2c1Sopenharmony_ci    if (currency.size() != CURRENCY_LEN) {
5969596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("Invalid currency code : %{public}s", currency.c_str());
5979596a2c1Sopenharmony_ci        return "";
5989596a2c1Sopenharmony_ci    }
5999596a2c1Sopenharmony_ci    bool isAlpha = true;
6009596a2c1Sopenharmony_ci    for (auto c : currency) {
6019596a2c1Sopenharmony_ci        isAlpha = std::isalpha(c);
6029596a2c1Sopenharmony_ci        if (!isAlpha) {
6039596a2c1Sopenharmony_ci            break;
6049596a2c1Sopenharmony_ci        }
6059596a2c1Sopenharmony_ci    }
6069596a2c1Sopenharmony_ci    if (isAlpha) {
6079596a2c1Sopenharmony_ci        return currency;
6089596a2c1Sopenharmony_ci    }
6099596a2c1Sopenharmony_ci    if (ReadISO4217Ddatas() && numToCurrency.find(currency) != numToCurrency.end()) {
6109596a2c1Sopenharmony_ci        return numToCurrency[currency];
6119596a2c1Sopenharmony_ci    }
6129596a2c1Sopenharmony_ci    HILOG_ERROR_I18N("Invalid currency code : %{public}s", currency.c_str());
6139596a2c1Sopenharmony_ci    return "";
6149596a2c1Sopenharmony_ci}
6159596a2c1Sopenharmony_ci} // namespace I18n
6169596a2c1Sopenharmony_ci} // namespace Global
6179596a2c1Sopenharmony_ci} // namespace OHOS
618