1/* 2 * Copyright (c) 2021-2022 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 "locale_config.h" 16 17#include <cctype> 18#include <sstream> 19#include "i18n_hilog.h" 20#include "ohos/init_data.h" 21#include "parameter.h" 22#include "unicode/ucurr.h" 23#include "unicode/uenum.h" 24#include "unicode/utypes.h" 25#include "utils.h" 26#include "number_format.h" 27 28namespace OHOS { 29namespace Global { 30namespace I18n { 31const char* NumberFormat::DEVICE_TYPE_NAME = "const.product.devicetype"; 32std::unordered_map<std::string, std::string> NumberFormat::numToCurrency = {}; 33bool NumberFormat::icuInitialized = NumberFormat::Init(); 34 35std::unordered_map<std::string, UNumberUnitWidth> NumberFormat::unitStyle = { 36 { "long", UNumberUnitWidth::UNUM_UNIT_WIDTH_FULL_NAME }, 37 { "short", UNumberUnitWidth::UNUM_UNIT_WIDTH_SHORT }, 38 { "narrow", UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW } 39}; 40 41std::unordered_map<std::string, UNumberUnitWidth> NumberFormat::currencyStyle = { 42 { "symbol", UNumberUnitWidth::UNUM_UNIT_WIDTH_SHORT }, 43 { "code", UNumberUnitWidth::UNUM_UNIT_WIDTH_ISO_CODE }, 44 { "name", UNumberUnitWidth::UNUM_UNIT_WIDTH_FULL_NAME }, 45 { "narrowSymbol", UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW } 46}; 47 48std::unordered_map<std::string, UNumberSignDisplay> NumberFormat::signAutoStyle = { 49 { "auto", UNumberSignDisplay::UNUM_SIGN_AUTO }, 50 { "never", UNumberSignDisplay::UNUM_SIGN_NEVER }, 51 { "always", UNumberSignDisplay::UNUM_SIGN_ALWAYS }, 52 { "exceptZero", UNumberSignDisplay::UNUM_SIGN_EXCEPT_ZERO } 53}; 54 55std::unordered_map<std::string, UNumberSignDisplay> NumberFormat::signAccountingStyle = { 56 { "auto", UNumberSignDisplay::UNUM_SIGN_ACCOUNTING }, 57 { "never", UNumberSignDisplay::UNUM_SIGN_NEVER }, 58 { "always", UNumberSignDisplay::UNUM_SIGN_ACCOUNTING_ALWAYS }, 59 { "exceptZero", UNumberSignDisplay::UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO } 60}; 61 62std::unordered_map<UMeasurementSystem, std::string> NumberFormat::measurementSystem = { 63 { UMeasurementSystem::UMS_SI, "SI" }, 64 { UMeasurementSystem::UMS_US, "US" }, 65 { UMeasurementSystem::UMS_UK, "UK" }, 66}; 67 68std::unordered_map<std::string, UNumberUnitWidth> NumberFormat::defaultUnitStyle = { 69 { "tablet", UNumberUnitWidth::UNUM_UNIT_WIDTH_FULL_NAME }, 70 { "2in1", UNumberUnitWidth::UNUM_UNIT_WIDTH_FULL_NAME }, 71 { "tv", UNumberUnitWidth::UNUM_UNIT_WIDTH_FULL_NAME }, 72 { "pc", UNumberUnitWidth::UNUM_UNIT_WIDTH_FULL_NAME }, 73 { "wearable", UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW }, 74 { "liteWearable", UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW }, 75 { "watch", UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW } 76}; 77 78std::unordered_map<std::string, UNumberUnitWidth> NumberFormat::defaultCurrencyStyle = { 79 { "wearable", UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW }, 80 { "liteWearable", UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW }, 81 { "watch", UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW } 82}; 83 84std::map<std::string, std::string> NumberFormat::RelativeTimeFormatConfigs = { 85 { "numeric", "auto" } 86}; 87 88NumberFormat::NumberFormat(const std::vector<std::string> &localeTags, std::map<std::string, std::string> &configs) 89{ 90 SetDefaultStyle(); 91 UErrorCode status = U_ZERO_ERROR; 92 std::unique_ptr<icu::LocaleBuilder> builder = nullptr; 93 builder = std::make_unique<icu::LocaleBuilder>(); 94 ParseConfigs(configs); 95 for (size_t i = 0; i < localeTags.size(); i++) { 96 std::string curLocale = localeTags[i]; 97 locale = icu::Locale::forLanguageTag(icu::StringPiece(curLocale), status); 98 if (U_FAILURE(status)) { 99 status = U_ZERO_ERROR; 100 continue; 101 } 102 if (LocaleInfo::allValidLocales.count(locale.getLanguage()) > 0) { 103 localeInfo = std::make_unique<LocaleInfo>(curLocale, configs); 104 CreateRelativeTimeFormat(curLocale); 105 if (!localeInfo->InitSuccess()) { 106 continue; 107 } 108 locale = localeInfo->GetLocale(); 109 localeBaseName = localeInfo->GetBaseName(); 110 numberFormat = icu::number::NumberFormatter::withLocale(locale); 111 icu::MeasureUnit::getAvailable(unitArray, MAX_UNIT_NUM, status); 112 if (!U_SUCCESS(status)) { 113 status = U_ZERO_ERROR; 114 continue; 115 } 116 createSuccess = true; 117 break; 118 } 119 } 120 if (!createSuccess) { 121 std::string systemLocale = LocaleConfig::GetSystemLocale(); 122 localeInfo = std::make_unique<LocaleInfo>(systemLocale, configs); 123 CreateRelativeTimeFormat(systemLocale); 124 if (localeInfo->InitSuccess()) { 125 locale = localeInfo->GetLocale(); 126 localeBaseName = localeInfo->GetBaseName(); 127 numberFormat = icu::number::NumberFormatter::withLocale(locale); 128 icu::MeasureUnit::getAvailable(unitArray, MAX_UNIT_NUM, status); 129 if (U_SUCCESS(status)) { 130 createSuccess = true; 131 } 132 } 133 } 134 if (createSuccess) { 135 InitProperties(); 136 } 137} 138 139NumberFormat::~NumberFormat() 140{ 141} 142 143void NumberFormat::CreateRelativeTimeFormat(const std::string& locale) 144{ 145 if (unitUsage == "elapsed-time-second") { 146 std::vector<std::string> locales = { locale }; 147 relativeTimeFormat = std::make_unique<RelativeTimeFormat>(locales, 148 RelativeTimeFormatConfigs); 149 } 150} 151 152void NumberFormat::InitProperties() 153{ 154 if (!currency.empty()) { 155 UErrorCode status = U_ZERO_ERROR; 156 numberFormat = 157 numberFormat.unit(icu::CurrencyUnit(icu::UnicodeString(currency.c_str()).getBuffer(), status)); 158 if (currencyDisplay != UNumberUnitWidth::UNUM_UNIT_WIDTH_SHORT) { 159 numberFormat = numberFormat.unitWidth(currencyDisplay); 160 } 161 } 162 if (!styleString.empty() && styleString == "percent") { 163 // 2 is the power of ten 164 numberFormat = numberFormat.unit(icu::NoUnit::percent()).scale(icu::number::Scale::powerOfTen(2)).precision( 165 icu::number::Precision::fixedFraction(0)); 166 } 167 if (!styleString.empty() && styleString == "unit") { 168 for (icu::MeasureUnit curUnit : unitArray) { 169 if (!strcmp(curUnit.getSubtype(), unit.c_str())) { 170 numberFormat = numberFormat.unit(curUnit); 171 unitType = curUnit.getType(); 172 } 173 } 174 UErrorCode status = U_ZERO_ERROR; 175 UMeasurementSystem measSys = ulocdata_getMeasurementSystem(localeBaseName.c_str(), &status); 176 if (U_SUCCESS(status) && measSys >= 0) { 177 unitMeasSys = measurementSystem[measSys]; 178 } 179 numberFormat = numberFormat.unitWidth(unitDisplay); 180 numberFormat = numberFormat.precision(icu::number::Precision::maxFraction(DEFAULT_FRACTION_DIGITS)); 181 } 182 if (!useGrouping.empty()) { 183 numberFormat = numberFormat.grouping((useGrouping == "true") ? 184 UNumberGroupingStrategy::UNUM_GROUPING_AUTO : UNumberGroupingStrategy::UNUM_GROUPING_OFF); 185 } 186 if (!currencySign.empty() || !signDisplayString.empty()) { 187 numberFormat = numberFormat.sign(signDisplay); 188 } 189 if (!notationString.empty()) { 190 numberFormat = numberFormat.notation(notation); 191 } 192 InitDigitsProperties(); 193} 194 195void NumberFormat::InitDigitsProperties() 196{ 197 int32_t status = 0; 198 if (!maximumSignificantDigits.empty() || !minimumSignificantDigits.empty()) { 199 int32_t maxSignificantDigits = ConvertString2Int(maximumSignificantDigits, status); 200 if (status == 0) { 201 numberFormat = numberFormat.precision(icu::number::Precision::maxSignificantDigits(maxSignificantDigits)); 202 } 203 204 status = 0; 205 int32_t minSignificantDigits = ConvertString2Int(minimumSignificantDigits, status); 206 if (status == 0) { 207 numberFormat = numberFormat.precision(icu::number::Precision::minSignificantDigits(minSignificantDigits)); 208 } 209 } else { 210 int32_t minIntegerDigits = ConvertString2Int(minimumIntegerDigits, status); 211 if (status == 0 && minIntegerDigits > 1) { 212 numberFormat = 213 numberFormat.integerWidth(icu::number::IntegerWidth::zeroFillTo(minIntegerDigits)); 214 } 215 216 int32_t minFdStatus = 0; 217 int32_t minFractionDigits = ConvertString2Int(minimumFractionDigits, minFdStatus); 218 int32_t maxFdStatus = 0; 219 int32_t maxFractionDigits = ConvertString2Int(maximumFractionDigits, maxFdStatus); 220 if (minFdStatus == 0 || maxFdStatus == 0) { 221 isSetFraction = true; 222 } 223 if (minFdStatus == 0 && maxFdStatus != 0) { 224 numberFormat = 225 numberFormat.precision(icu::number::Precision::minFraction(minFractionDigits)); 226 } else if (minFdStatus != 0 && maxFdStatus == 0) { 227 numberFormat = 228 numberFormat.precision(icu::number::Precision::maxFraction(maxFractionDigits)); 229 } else if (minFdStatus == 0 && maxFdStatus == 0) { 230 numberFormat = 231 numberFormat.precision(icu::number::Precision::minMaxFraction(minFractionDigits, maxFractionDigits)); 232 } 233 } 234} 235 236void NumberFormat::ParseConfigs(std::map<std::string, std::string> &configs) 237{ 238 if (configs.count("signDisplay") > 0) { 239 signDisplayString = configs["signDisplay"]; 240 } 241 if (signAutoStyle.count(signDisplayString) > 0) { 242 signDisplay = signAutoStyle[signDisplayString]; 243 } 244 if (configs.count("style") > 0) { 245 styleString = configs["style"]; 246 } 247 if (styleString == "unit" && configs.count("unit") > 0) { 248 unit = configs["unit"]; 249 if (configs.count("unitDisplay") > 0) { 250 unitDisplayString = configs["unitDisplay"]; 251 if (unitStyle.count(unitDisplayString) > 0) { 252 unitDisplay = unitStyle[unitDisplayString]; 253 } 254 } 255 if (configs.count("unitUsage") > 0) { 256 unitUsage = configs["unitUsage"]; 257 } 258 } 259 if (styleString == "currency" && configs.count("currency") > 0) { 260 currency = GetCurrencyFromConfig(configs["currency"]); 261 if (configs.count("currencySign") > 0) { 262 currencySign = configs["currencySign"]; 263 } 264 if (currencySign.compare("accounting") == 0 && signAccountingStyle.count(signDisplayString) > 0) { 265 signDisplay = signAccountingStyle[signDisplayString]; 266 } 267 if (configs.count("currencyDisplay") > 0 && currencyStyle.count(configs["currencyDisplay"]) > 0) { 268 currencyDisplayString = configs["currencyDisplay"]; 269 currencyDisplay = currencyStyle[currencyDisplayString]; 270 } 271 } 272 ParseDigitsConfigs(configs); 273} 274 275void NumberFormat::ParseDigitsConfigs(std::map<std::string, std::string> &configs) 276{ 277 if (configs.count("notation") > 0) { 278 notationString = configs["notation"]; 279 if (notationString == "scientific") { 280 notation = icu::number::Notation::scientific(); 281 } else if (notationString == "engineering") { 282 notation = icu::number::Notation::engineering(); 283 } 284 if (notationString == "compact") { 285 if (configs.count("compactDisplay") > 0) { 286 compactDisplay = configs["compactDisplay"]; 287 } 288 if (compactDisplay == "long") { 289 notation = icu::number::Notation::compactLong(); 290 } else { 291 notation = icu::number::Notation::compactShort(); 292 } 293 } 294 } 295 if (configs.count("minimumIntegerDigits") > 0) { 296 minimumIntegerDigits = configs["minimumIntegerDigits"]; 297 } 298 if (configs.count("minimumFractionDigits") > 0) { 299 minimumFractionDigits = configs["minimumFractionDigits"]; 300 } 301 if (configs.count("maximumFractionDigits") > 0) { 302 maximumFractionDigits = configs["maximumFractionDigits"]; 303 } 304 if (configs.count("minimumSignificantDigits") > 0) { 305 minimumSignificantDigits = configs["minimumSignificantDigits"]; 306 } 307 if (configs.count("maximumSignificantDigits") > 0) { 308 maximumSignificantDigits = configs["maximumSignificantDigits"]; 309 } 310 if (configs.count("numberingSystem") > 0) { 311 numberingSystem = configs["numberingSystem"]; 312 } 313 if (configs.count("useGrouping") > 0) { 314 useGrouping = configs["useGrouping"]; 315 } 316 if (configs.count("localeMatcher") > 0) { 317 localeMatcher = configs["localeMatcher"]; 318 } 319} 320 321void NumberFormat::SetUnit(std::string &preferredUnit) 322{ 323 if (preferredUnit.empty()) { 324 return; 325 } 326 for (icu::MeasureUnit curUnit : unitArray) { 327 if (!strcmp(curUnit.getSubtype(), preferredUnit.c_str())) { 328 numberFormat = numberFormat.unit(curUnit); 329 } 330 } 331} 332 333std::string NumberFormat::Format(double number) 334{ 335 if (!createSuccess) { 336 return PseudoLocalizationProcessor(""); 337 } 338 double finalNumber = number; 339 std::string finalUnit = unit; 340 if ((unitUsage == "size-file-byte" || unitUsage == "size-shortfile-byte") && ConvertByte(finalNumber, finalUnit)) { 341 SetUnit(finalUnit); 342 SetPrecisionWithByte(finalNumber, finalUnit); 343 } else if (unitUsage == "elapsed-time-second" && ConvertDate(finalNumber, finalUnit) && 344 relativeTimeFormat != nullptr) { 345 return relativeTimeFormat->Format(finalNumber, finalUnit); 346 } else if (!unitUsage.empty()) { 347 std::vector<std::string> preferredUnits; 348 if (unitUsage == "default") { 349 GetDefaultPreferredUnit(localeInfo->GetRegion(), unitType, preferredUnits); 350 } else { 351 GetPreferredUnit(localeInfo->GetRegion(), unitUsage, preferredUnits); 352 } 353 std::map<double, std::string> preferredValuesOverOne; 354 std::map<double, std::string> preferredValuesUnderOne; 355 double num = number; 356 for (size_t i = 0; i < preferredUnits.size(); i++) { 357 int status = Convert(num, unit, unitMeasSys, preferredUnits[i], unitMeasSys); 358 if (!status) { 359 continue; 360 } 361 if (num >= 1) { 362 preferredValuesOverOne.insert(std::make_pair(num, preferredUnits[i])); 363 } else { 364 preferredValuesUnderOne.insert(std::make_pair(num, preferredUnits[i])); 365 } 366 } 367 std::string preferredUnit; 368 if (preferredValuesOverOne.size() > 0) { 369 finalNumber = preferredValuesOverOne.begin()->first; 370 preferredUnit = preferredValuesOverOne.begin()->second; 371 } else if (preferredValuesUnderOne.size() > 0) { 372 finalNumber = preferredValuesUnderOne.rbegin()->first; 373 preferredUnit = preferredValuesUnderOne.rbegin()->second; 374 } 375 SetUnit(preferredUnit); 376 } 377 std::string result; 378 UErrorCode status = U_ZERO_ERROR; 379 numberFormat.formatDouble(finalNumber, status).toString(status).toUTF8String(result); 380 return PseudoLocalizationProcessor(result); 381} 382 383void NumberFormat::GetResolvedOptions(std::map<std::string, std::string> &map) 384{ 385 map.insert(std::make_pair("locale", localeBaseName)); 386 if (!styleString.empty()) { 387 map.insert(std::make_pair("style", styleString)); 388 } 389 if (!currency.empty()) { 390 map.insert(std::make_pair("currency", currency)); 391 } 392 if (!currencySign.empty()) { 393 map.insert(std::make_pair("currencySign", currencySign)); 394 } 395 if (!currencyDisplayString.empty()) { 396 map.insert(std::make_pair("currencyDisplay", currencyDisplayString)); 397 } 398 if (!signDisplayString.empty()) { 399 map.insert(std::make_pair("signDisplay", signDisplayString)); 400 } 401 if (!compactDisplay.empty()) { 402 map.insert(std::make_pair("compactDisplay", compactDisplay)); 403 } 404 if (!unitDisplayString.empty()) { 405 map.insert(std::make_pair("unitDisplay", unitDisplayString)); 406 } 407 if (!unitUsage.empty()) { 408 map.insert(std::make_pair("unitUsage", unitUsage)); 409 } 410 if (!unit.empty()) { 411 map.insert(std::make_pair("unit", unit)); 412 } 413 GetDigitsResolvedOptions(map); 414} 415 416void NumberFormat::GetDigitsResolvedOptions(std::map<std::string, std::string> &map) 417{ 418 if (!numberingSystem.empty()) { 419 map.insert(std::make_pair("numberingSystem", numberingSystem)); 420 } else if (!(localeInfo->GetNumberingSystem()).empty()) { 421 map.insert(std::make_pair("numberingSystem", localeInfo->GetNumberingSystem())); 422 } else { 423 UErrorCode status = U_ZERO_ERROR; 424 auto numSys = std::unique_ptr<icu::NumberingSystem>(icu::NumberingSystem::createInstance(locale, status)); 425 if (U_SUCCESS(status)) { 426 map.insert(std::make_pair("numberingSystem", numSys->getName())); 427 } 428 } 429 if (!useGrouping.empty()) { 430 map.insert(std::make_pair("useGrouping", useGrouping)); 431 } 432 if (!minimumIntegerDigits.empty()) { 433 map.insert(std::make_pair("minimumIntegerDigits", minimumIntegerDigits)); 434 } 435 if (!minimumFractionDigits.empty()) { 436 map.insert(std::make_pair("minimumFractionDigits", minimumFractionDigits)); 437 } 438 if (!maximumFractionDigits.empty()) { 439 map.insert(std::make_pair("maximumFractionDigits", maximumFractionDigits)); 440 } 441 if (!minimumSignificantDigits.empty()) { 442 map.insert(std::make_pair("minimumSignificantDigits", minimumSignificantDigits)); 443 } 444 if (!maximumSignificantDigits.empty()) { 445 map.insert(std::make_pair("maximumSignificantDigits", maximumSignificantDigits)); 446 } 447 if (!localeMatcher.empty()) { 448 map.insert(std::make_pair("localeMatcher", localeMatcher)); 449 } 450 if (!notationString.empty()) { 451 map.insert(std::make_pair("notation", notationString)); 452 } 453} 454 455void NumberFormat::SetPrecisionWithByte(double number, const std::string& finalUnit) 456{ 457 if (isSetFraction) { 458 return; 459 } 460 int32_t FractionDigits = -1; 461 // 100 is the threshold between different decimal 462 if (finalUnit == "byte" || number >= 100) { 463 FractionDigits = 0; 464 } else if (number < 1) { 465 // 2 is the number of significant digits in the decimal 466 FractionDigits = 2; 467 // 10 is the threshold between different decimal 468 } else if (number < 10) { 469 if (unitUsage == "size-shortfile-byte") { 470 FractionDigits = 1; 471 } else { 472 // 2 is the number of significant digits in the decimal 473 FractionDigits = 2; 474 } 475 } else { 476 if (unitUsage == "size-shortfile-byte") { 477 FractionDigits = 0; 478 } else { 479 // 2 is the number of significant digits in the decimal 480 FractionDigits = 2; 481 } 482 } 483 if (FractionDigits != -1) { 484 numberFormat = numberFormat.precision(icu::number::Precision::minMaxFraction(FractionDigits, FractionDigits)); 485 } 486} 487 488std::string NumberFormat::GetCurrency() const 489{ 490 return currency; 491} 492 493std::string NumberFormat::GetCurrencySign() const 494{ 495 return currencySign; 496} 497 498std::string NumberFormat::GetStyle() const 499{ 500 return styleString; 501} 502 503std::string NumberFormat::GetNumberingSystem() const 504{ 505 return numberingSystem; 506} 507 508std::string NumberFormat::GetUseGrouping() const 509{ 510 return useGrouping; 511} 512 513std::string NumberFormat::GetMinimumIntegerDigits() const 514{ 515 return minimumIntegerDigits; 516} 517 518std::string NumberFormat::GetMinimumFractionDigits() const 519{ 520 return minimumFractionDigits; 521} 522 523std::string NumberFormat::GetMaximumFractionDigits() const 524{ 525 return maximumFractionDigits; 526} 527 528std::string NumberFormat::GetMinimumSignificantDigits() const 529{ 530 return minimumSignificantDigits; 531} 532 533std::string NumberFormat::GetMaximumSignificantDigits() const 534{ 535 return maximumSignificantDigits; 536} 537 538std::string NumberFormat::GetLocaleMatcher() const 539{ 540 return localeMatcher; 541} 542 543bool NumberFormat::Init() 544{ 545 SetHwIcuDirectory(); 546 return true; 547} 548 549void NumberFormat::SetDefaultStyle() 550{ 551 char value[BUFFER_LEN]; 552 int code = GetParameter(DEVICE_TYPE_NAME, "", value, BUFFER_LEN); 553 if (code > 0) { 554 std::string deviceType = value; 555 if (defaultUnitStyle.find(deviceType) != defaultUnitStyle.end()) { 556 unitDisplay = defaultUnitStyle[deviceType]; 557 } 558 if (defaultCurrencyStyle.find(deviceType) != defaultCurrencyStyle.end()) { 559 currencyDisplay = defaultCurrencyStyle[deviceType]; 560 } 561 } 562} 563 564bool NumberFormat::ReadISO4217Ddatas() 565{ 566 if (numToCurrency.size()) { 567 return true; 568 } 569 UErrorCode status = U_ZERO_ERROR; 570 const char *currentCurrency; 571 UEnumeration *currencies = ucurr_openISOCurrencies(UCURR_ALL, &status); 572 if (U_FAILURE(status)) { 573 return false; 574 } 575 576 UChar code[CURRENCY_LEN + 1]; // +1 includes the NUL 577 int32_t length = 0; 578 while ((currentCurrency = uenum_next(currencies, &length, &status)) != NULL) { 579 u_charsToUChars(currentCurrency, code, length + 1); // +1 includes the NUL 580 const UChar* currencyCode = code; 581 int32_t numCode = ucurr_getNumericCode(currencyCode); 582 if (numCode == 0) { 583 continue; 584 } 585 std::stringstream ss; 586 ss << std::setw(CURRENCY_LEN) << std::setfill('0') << numCode; // fill with '0' 587 numToCurrency.insert(std::make_pair<std::string, std::string>(ss.str(), currentCurrency)); 588 } 589 uenum_close(currencies); 590 return !numToCurrency.empty(); 591} 592 593std::string NumberFormat::GetCurrencyFromConfig(const std::string& currency) 594{ 595 if (currency.size() != CURRENCY_LEN) { 596 HILOG_ERROR_I18N("Invalid currency code : %{public}s", currency.c_str()); 597 return ""; 598 } 599 bool isAlpha = true; 600 for (auto c : currency) { 601 isAlpha = std::isalpha(c); 602 if (!isAlpha) { 603 break; 604 } 605 } 606 if (isAlpha) { 607 return currency; 608 } 609 if (ReadISO4217Ddatas() && numToCurrency.find(currency) != numToCurrency.end()) { 610 return numToCurrency[currency]; 611 } 612 HILOG_ERROR_I18N("Invalid currency code : %{public}s", currency.c_str()); 613 return ""; 614} 615} // namespace I18n 616} // namespace Global 617} // namespace OHOS 618