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 16#include "intl_addon.h" 17 18#include <vector> 19#include <set> 20#include "error_util.h" 21#include "i18n_hilog.h" 22#include "js_utils.h" 23#include "node_api.h" 24#include "utils.h" 25 26namespace OHOS { 27namespace Global { 28namespace I18n { 29static thread_local napi_ref *g_constructor = nullptr; 30 31IntlAddon::IntlAddon() : env_(nullptr) {} 32 33IntlAddon::~IntlAddon() 34{ 35} 36 37void IntlAddon::Destructor(napi_env env, void *nativeObject, void *hint) 38{ 39 if (!nativeObject) { 40 return; 41 } 42 delete reinterpret_cast<IntlAddon *>(nativeObject); 43 nativeObject = nullptr; 44} 45 46napi_value IntlAddon::SetProperty(napi_env env, napi_callback_info info) 47{ 48 // do nothing but provided as an input parameter for DECLARE_NAPI_GETTER_SETTER; 49 napi_value result = nullptr; 50 NAPI_CALL(env, napi_get_undefined(env, &result)); 51 return result; 52} 53 54napi_value IntlAddon::InitLocale(napi_env env, napi_value exports) 55{ 56 napi_status status = napi_ok; 57 napi_property_descriptor properties[] = { 58 DECLARE_NAPI_GETTER_SETTER("language", GetLanguage, SetProperty), 59 DECLARE_NAPI_GETTER_SETTER("baseName", GetBaseName, SetProperty), 60 DECLARE_NAPI_GETTER_SETTER("region", GetRegion, SetProperty), 61 DECLARE_NAPI_GETTER_SETTER("script", GetScript, SetProperty), 62 DECLARE_NAPI_GETTER_SETTER("calendar", GetCalendar, SetProperty), 63 DECLARE_NAPI_GETTER_SETTER("collation", GetCollation, SetProperty), 64 DECLARE_NAPI_GETTER_SETTER("hourCycle", GetHourCycle, SetProperty), 65 DECLARE_NAPI_GETTER_SETTER("numberingSystem", GetNumberingSystem, SetProperty), 66 DECLARE_NAPI_GETTER_SETTER("numeric", GetNumeric, SetProperty), 67 DECLARE_NAPI_GETTER_SETTER("caseFirst", GetCaseFirst, SetProperty), 68 DECLARE_NAPI_FUNCTION("toString", ToString), 69 DECLARE_NAPI_FUNCTION("minimize", Minimize), 70 DECLARE_NAPI_FUNCTION("maximize", Maximize), 71 }; 72 73 napi_value constructor = nullptr; 74 status = napi_define_class(env, "Locale", NAPI_AUTO_LENGTH, LocaleConstructor, nullptr, 75 sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor); 76 if (status != napi_ok) { 77 HILOG_ERROR_I18N("Define class failed when InitLocale"); 78 return nullptr; 79 } 80 81 status = napi_set_named_property(env, exports, "Locale", constructor); 82 if (status != napi_ok) { 83 HILOG_ERROR_I18N("Set property failed when InitLocale"); 84 return nullptr; 85 } 86 g_constructor = new (std::nothrow) napi_ref; 87 if (!g_constructor) { 88 HILOG_ERROR_I18N("Failed to create ref at init"); 89 return nullptr; 90 } 91 status = napi_create_reference(env, constructor, 1, g_constructor); 92 if (status != napi_ok) { 93 HILOG_ERROR_I18N("Failed to create reference at init"); 94 return nullptr; 95 } 96 return exports; 97} 98 99napi_value IntlAddon::InitDateTimeFormat(napi_env env, napi_value exports) 100{ 101 napi_status status = napi_ok; 102 napi_property_descriptor properties[] = { 103 DECLARE_NAPI_FUNCTION("format", FormatDateTime), 104 DECLARE_NAPI_FUNCTION("formatRange", FormatDateTimeRange), 105 DECLARE_NAPI_FUNCTION("resolvedOptions", GetDateTimeResolvedOptions) 106 }; 107 108 napi_value constructor = nullptr; 109 status = napi_define_class(env, "DateTimeFormat", NAPI_AUTO_LENGTH, DateTimeFormatConstructor, nullptr, 110 sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor); 111 if (status != napi_ok) { 112 HILOG_ERROR_I18N("Define class failed when InitDateTimeFormat"); 113 return nullptr; 114 } 115 116 status = napi_set_named_property(env, exports, "DateTimeFormat", constructor); 117 if (status != napi_ok) { 118 HILOG_ERROR_I18N("Set property failed when InitDateTimeFormat"); 119 return nullptr; 120 } 121 return exports; 122} 123 124napi_value IntlAddon::InitRelativeTimeFormat(napi_env env, napi_value exports) 125{ 126 napi_status status = napi_ok; 127 napi_property_descriptor properties[] = { 128 DECLARE_NAPI_FUNCTION("format", FormatRelativeTime), 129 DECLARE_NAPI_FUNCTION("formatToParts", FormatToParts), 130 DECLARE_NAPI_FUNCTION("resolvedOptions", GetRelativeTimeResolvedOptions) 131 }; 132 133 napi_value constructor = nullptr; 134 status = napi_define_class(env, "RelativeTimeFormat", NAPI_AUTO_LENGTH, RelativeTimeFormatConstructor, nullptr, 135 sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor); 136 if (status != napi_ok) { 137 HILOG_ERROR_I18N("Define class failed when InitRelativeTimeFormat"); 138 return nullptr; 139 } 140 141 status = napi_set_named_property(env, exports, "RelativeTimeFormat", constructor); 142 if (status != napi_ok) { 143 HILOG_ERROR_I18N("Set property failed when InitRelativeTimeFormat"); 144 return nullptr; 145 } 146 return exports; 147} 148 149napi_value IntlAddon::InitNumberFormat(napi_env env, napi_value exports) 150{ 151 napi_status status = napi_ok; 152 napi_property_descriptor properties[] = { 153 DECLARE_NAPI_FUNCTION("format", FormatNumber), 154 DECLARE_NAPI_FUNCTION("resolvedOptions", GetNumberResolvedOptions) 155 }; 156 157 napi_value constructor = nullptr; 158 status = napi_define_class(env, "NumberFormat", NAPI_AUTO_LENGTH, NumberFormatConstructor, nullptr, 159 sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor); 160 if (status != napi_ok) { 161 HILOG_ERROR_I18N("Define class failed when InitNumberFormat"); 162 return nullptr; 163 } 164 165 status = napi_set_named_property(env, exports, "NumberFormat", constructor); 166 if (status != napi_ok) { 167 HILOG_ERROR_I18N("Set property failed when InitNumberFormat"); 168 return nullptr; 169 } 170 return exports; 171} 172 173void GetOptionValue(napi_env env, napi_value options, const std::string &optionName, 174 std::map<std::string, std::string> &map) 175{ 176 napi_value optionValue = nullptr; 177 napi_valuetype type = napi_undefined; 178 napi_status status = napi_typeof(env, options, &type); 179 if (status != napi_ok && type != napi_object) { 180 HILOG_ERROR_I18N("Get option failed, option is not an object"); 181 return; 182 } 183 bool hasProperty = false; 184 napi_status propStatus = napi_has_named_property(env, options, optionName.c_str(), &hasProperty); 185 if (propStatus == napi_ok && hasProperty) { 186 status = napi_get_named_property(env, options, optionName.c_str(), &optionValue); 187 if (status == napi_ok) { 188 size_t len = 0; 189 napi_get_value_string_utf8(env, optionValue, nullptr, 0, &len); 190 std::vector<char> optionBuf(len + 1); 191 status = napi_get_value_string_utf8(env, optionValue, optionBuf.data(), len + 1, &len); 192 if (status != napi_ok) { 193 return; 194 } 195 map.insert(make_pair(optionName, optionBuf.data())); 196 } 197 } 198} 199 200int64_t GetIntegerOptionValue(napi_env env, napi_value options, const std::string &optionName, 201 std::map<std::string, std::string> &map) 202{ 203 napi_value optionValue = nullptr; 204 int64_t integerValue = -1; 205 napi_valuetype type = napi_undefined; 206 napi_status status = napi_typeof(env, options, &type); 207 if (status != napi_ok && type != napi_object) { 208 HILOG_ERROR_I18N("GetIntegerOptionValue: Set option failed, option is not an object"); 209 return integerValue; 210 } 211 bool hasProperty = false; 212 napi_status propStatus = napi_has_named_property(env, options, optionName.c_str(), &hasProperty); 213 if (propStatus == napi_ok && hasProperty) { 214 status = napi_get_named_property(env, options, optionName.c_str(), &optionValue); 215 if (status == napi_ok) { 216 status = napi_get_value_int64(env, optionValue, &integerValue); 217 if (status == napi_ok) { 218 map.insert(make_pair(optionName, std::to_string(integerValue))); 219 } 220 } 221 } 222 return integerValue; 223} 224 225void GetBoolOptionValue(napi_env env, napi_value options, const std::string &optionName, 226 std::map<std::string, std::string> &map) 227{ 228 napi_value optionValue = nullptr; 229 napi_valuetype type = napi_undefined; 230 napi_status status = napi_typeof(env, options, &type); 231 if (status != napi_ok && type != napi_object) { 232 HILOG_ERROR_I18N("GetBoolOptionValue: Set option failed, option is not an object"); 233 return; 234 } 235 bool hasProperty = false; 236 napi_status propStatus = napi_has_named_property(env, options, optionName.c_str(), &hasProperty); 237 if (propStatus == napi_ok && hasProperty) { 238 status = napi_get_named_property(env, options, optionName.c_str(), &optionValue); 239 if (status == napi_ok) { 240 bool boolValue = false; 241 napi_get_value_bool(env, optionValue, &boolValue); 242 std::string value = boolValue ? "true" : "false"; 243 map.insert(make_pair(optionName, value)); 244 } 245 } 246} 247 248void GetDateOptionValues(napi_env env, napi_value options, std::map<std::string, std::string> &map) 249{ 250 GetOptionValue(env, options, "calendar", map); 251 GetOptionValue(env, options, "dateStyle", map); 252 GetOptionValue(env, options, "timeStyle", map); 253 GetOptionValue(env, options, "hourCycle", map); 254 GetOptionValue(env, options, "timeZone", map); 255 GetOptionValue(env, options, "timeZoneName", map); 256 GetOptionValue(env, options, "numberingSystem", map); 257 GetBoolOptionValue(env, options, "hour12", map); 258 GetOptionValue(env, options, "weekday", map); 259 GetOptionValue(env, options, "era", map); 260 GetOptionValue(env, options, "year", map); 261 GetOptionValue(env, options, "month", map); 262 GetOptionValue(env, options, "day", map); 263 GetOptionValue(env, options, "hour", map); 264 GetOptionValue(env, options, "minute", map); 265 GetOptionValue(env, options, "second", map); 266 GetOptionValue(env, options, "localeMatcher", map); 267 GetOptionValue(env, options, "formatMatcher", map); 268 GetOptionValue(env, options, "dayPeriod", map); 269} 270 271void GetRelativeTimeOptionValues(napi_env env, napi_value options, std::map<std::string, std::string> &map) 272{ 273 GetOptionValue(env, options, "localeMatcher", map); 274 GetOptionValue(env, options, "numeric", map); 275 GetOptionValue(env, options, "style", map); 276} 277 278std::string GetLocaleTag(napi_env env, napi_value argv) 279{ 280 std::string localeTag = ""; 281 std::vector<char> buf; 282 if (argv != nullptr) { 283 napi_valuetype valueType = napi_valuetype::napi_undefined; 284 napi_typeof(env, argv, &valueType); 285 if (valueType != napi_valuetype::napi_string) { 286 HILOG_ERROR_I18N("GetLocaleTag: Parameter type does not match"); 287 return ""; 288 } 289 size_t len = 0; 290 napi_status status = napi_get_value_string_utf8(env, argv, nullptr, 0, &len); 291 if (status != napi_ok) { 292 HILOG_ERROR_I18N("GetLocaleTag -> string: Get locale tag length failed"); 293 return ""; 294 } 295 buf.resize(len + 1); 296 status = napi_get_value_string_utf8(env, argv, buf.data(), len + 1, &len); 297 if (status != napi_ok) { 298 HILOG_ERROR_I18N("GetLocaleTag: Get locale tag failed"); 299 return ""; 300 } 301 localeTag = buf.data(); 302 } else { 303 localeTag = ""; 304 } 305 return localeTag; 306} 307 308napi_value IntlAddon::LocaleConstructor(napi_env env, napi_callback_info info) 309{ 310 size_t argc = 2; 311 napi_value argv[2] = { nullptr }; 312 napi_value thisVar = nullptr; 313 void *data = nullptr; 314 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 315 if (status != napi_ok) { 316 return nullptr; 317 } 318 std::string localeTag = GetLocaleTag(env, argc > 0 ? argv[0] : nullptr); 319 320 std::map<std::string, std::string> map = {}; 321 if (argc > 1) { 322 GetOptionValue(env, argv[1], "calendar", map); 323 GetOptionValue(env, argv[1], "collation", map); 324 GetOptionValue(env, argv[1], "hourCycle", map); 325 GetOptionValue(env, argv[1], "numberingSystem", map); 326 GetBoolOptionValue(env, argv[1], "numeric", map); 327 GetOptionValue(env, argv[1], "caseFirst", map); 328 } 329 std::unique_ptr<IntlAddon> obj = nullptr; 330 obj = std::make_unique<IntlAddon>(); 331 status = 332 napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), IntlAddon::Destructor, nullptr, nullptr); 333 if (status != napi_ok) { 334 HILOG_ERROR_I18N("LocaleConstructor: Wrap IntlAddon failed"); 335 return nullptr; 336 } 337 if (!obj->InitLocaleContext(env, info, localeTag, map)) { 338 return nullptr; 339 } 340 obj.release(); 341 return thisVar; 342} 343 344bool IntlAddon::InitLocaleContext(napi_env env, napi_callback_info info, const std::string localeTag, 345 std::map<std::string, std::string> &map) 346{ 347 napi_value global = nullptr; 348 napi_status status = napi_get_global(env, &global); 349 if (status != napi_ok) { 350 HILOG_ERROR_I18N("InitLocaleContext: Get global failed"); 351 return false; 352 } 353 env_ = env; 354 locale_ = std::make_unique<LocaleInfo>(localeTag, map); 355 356 return locale_ != nullptr; 357} 358 359void GetLocaleTags(napi_env env, napi_value rawLocaleTag, std::vector<std::string> &localeTags) 360{ 361 size_t len = 0; 362 napi_status status = napi_get_value_string_utf8(env, rawLocaleTag, nullptr, 0, &len); 363 if (status != napi_ok) { 364 HILOG_ERROR_I18N("GetLocaleTag -> void: Get locale tag length failed"); 365 return; 366 } 367 std::vector<char> buf(len + 1); 368 status = napi_get_value_string_utf8(env, rawLocaleTag, buf.data(), len + 1, &len); 369 if (status != napi_ok) { 370 HILOG_ERROR_I18N("GetLocaleTags: Get locale tag failed"); 371 return; 372 } 373 localeTags.push_back(buf.data()); 374} 375 376napi_value IntlAddon::DateTimeFormatConstructor(napi_env env, napi_callback_info info) 377{ 378 size_t argc = 2; 379 napi_value argv[2] = { nullptr }; 380 napi_value thisVar = nullptr; 381 void *data = nullptr; 382 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 383 if (status != napi_ok) { 384 return nullptr; 385 } 386 std::vector<std::string> localeTags; 387 if (argc > 0) { 388 napi_valuetype valueType = napi_valuetype::napi_undefined; 389 napi_typeof(env, argv[0], &valueType); 390 bool isArray = false; 391 napi_is_array(env, argv[0], &isArray); 392 if (valueType == napi_valuetype::napi_string) { 393 GetLocaleTags(env, argv[0], localeTags); 394 } else if (isArray) { 395 uint32_t arrayLength = 0; 396 napi_get_array_length(env, argv[0], &arrayLength); 397 napi_value element = nullptr; 398 for (uint32_t i = 0; i < arrayLength; i++) { 399 napi_get_element(env, argv[0], i, &element); 400 GetLocaleTags(env, element, localeTags); 401 } 402 } 403 } 404 std::map<std::string, std::string> map = {}; 405 if (argc > 1) { 406 GetDateOptionValues(env, argv[1], map); 407 } 408 std::unique_ptr<IntlAddon> obj = nullptr; 409 obj = std::make_unique<IntlAddon>(); 410 status = 411 napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), IntlAddon::Destructor, nullptr, nullptr); 412 if (status != napi_ok) { 413 HILOG_ERROR_I18N("DateTimeFormatConstructor: Wrap IntlAddon failed"); 414 return nullptr; 415 } 416 if (!obj->InitDateTimeFormatContext(env, info, localeTags, map)) { 417 HILOG_ERROR_I18N("DateTimeFormatConstructor: Init DateTimeFormat failed"); 418 return nullptr; 419 } 420 obj.release(); 421 return thisVar; 422} 423 424bool IntlAddon::InitDateTimeFormatContext(napi_env env, napi_callback_info info, std::vector<std::string> localeTags, 425 std::map<std::string, std::string> &map) 426{ 427 napi_value global = nullptr; 428 napi_status status = napi_get_global(env, &global); 429 if (status != napi_ok) { 430 HILOG_ERROR_I18N("InitDateTimeFormatContext: Get global failed"); 431 return false; 432 } 433 env_ = env; 434 datefmt_ = DateTimeFormat::CreateInstance(localeTags, map); 435 436 return datefmt_ != nullptr; 437} 438 439napi_value IntlAddon::RelativeTimeFormatConstructor(napi_env env, napi_callback_info info) 440{ 441 size_t argc = 2; 442 napi_value argv[2] = { nullptr }; 443 napi_value thisVar = nullptr; 444 void *data = nullptr; 445 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 446 if (status != napi_ok) { 447 return nullptr; 448 } 449 std::vector<std::string> localeTags; 450 if (argc > 0) { 451 napi_valuetype valueType = napi_valuetype::napi_undefined; 452 napi_typeof(env, argv[0], &valueType); 453 bool isArray = false; 454 napi_is_array(env, argv[0], &isArray); 455 if (valueType == napi_valuetype::napi_string) { 456 GetLocaleTags(env, argv[0], localeTags); 457 } else if (isArray) { 458 uint32_t arrayLength = 0; 459 napi_get_array_length(env, argv[0], &arrayLength); 460 napi_value element = nullptr; 461 for (uint32_t i = 0; i < arrayLength; i++) { 462 napi_get_element(env, argv[0], i, &element); 463 GetLocaleTags(env, element, localeTags); 464 } 465 } 466 } 467 std::map<std::string, std::string> map = {}; 468 if (argc > 1) { 469 GetRelativeTimeOptionValues(env, argv[1], map); 470 } 471 std::unique_ptr<IntlAddon> obj = nullptr; 472 obj = std::make_unique<IntlAddon>(); 473 status = 474 napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), IntlAddon::Destructor, nullptr, nullptr); 475 if (status != napi_ok) { 476 HILOG_ERROR_I18N("RelativeTimeFormatConstructor: Wrap IntlAddon failed"); 477 return nullptr; 478 } 479 if (!obj->InitRelativeTimeFormatContext(env, info, localeTags, map)) { 480 HILOG_ERROR_I18N("Init RelativeTimeFormat failed"); 481 return nullptr; 482 } 483 obj.release(); 484 return thisVar; 485} 486 487bool IntlAddon::InitRelativeTimeFormatContext(napi_env env, napi_callback_info info, 488 std::vector<std::string> localeTags, std::map<std::string, std::string> &map) 489{ 490 env_ = env; 491 relativetimefmt_ = std::make_unique<RelativeTimeFormat>(localeTags, map); 492 493 return relativetimefmt_ != nullptr; 494} 495 496napi_value IntlAddon::FormatDateTime(napi_env env, napi_callback_info info) 497{ 498 size_t argc = 1; 499 napi_value argv[1] = { 0 }; 500 napi_value thisVar = nullptr; 501 void *data = nullptr; 502 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 503 504 int64_t milliseconds = GetMilliseconds(env, argv, 0); 505 if (milliseconds == -1) { 506 return nullptr; 507 } 508 IntlAddon *obj = nullptr; 509 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 510 if (status != napi_ok || !obj || !obj->datefmt_) { 511 HILOG_ERROR_I18N("FormatDateTime: Get DateTimeFormat object failed"); 512 return nullptr; 513 } 514 std::string value = obj->datefmt_->Format(milliseconds); 515 napi_value result = nullptr; 516 status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result); 517 if (status != napi_ok) { 518 HILOG_ERROR_I18N("FormatDateTime: Create format string failed"); 519 return nullptr; 520 } 521 return result; 522} 523 524napi_value IntlAddon::FormatDateTimeRange(napi_env env, napi_callback_info info) 525{ 526 size_t argc = 2; 527 napi_value argv[2] = { nullptr }; 528 napi_value thisVar = nullptr; 529 void *data = nullptr; 530 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 531 if (argc < FUNC_ARGS_COUNT) { 532 HILOG_ERROR_I18N("Parameter wrong"); 533 return nullptr; 534 } 535 int64_t firstMilliseconds = GetMilliseconds(env, argv, 0); 536 int64_t secondMilliseconds = GetMilliseconds(env, argv, 1); 537 if (firstMilliseconds == -1 || secondMilliseconds == -1) { 538 return nullptr; 539 } 540 IntlAddon *obj = nullptr; 541 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 542 if (status != napi_ok || !obj || !obj->datefmt_) { 543 HILOG_ERROR_I18N("FormatDateTimeRange: Get DateTimeFormat object failed"); 544 return nullptr; 545 } 546 std::string value = obj->datefmt_->FormatRange(firstMilliseconds, secondMilliseconds); 547 napi_value result = nullptr; 548 status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result); 549 if (status != napi_ok) { 550 HILOG_ERROR_I18N("FormatDateTimeRange: Create format string failed"); 551 return nullptr; 552 } 553 return result; 554} 555 556void GetNumberOptionValues(napi_env env, napi_value options, std::map<std::string, std::string> &map) 557{ 558 GetOptionValue(env, options, "currency", map); 559 GetOptionValue(env, options, "currencySign", map); 560 GetOptionValue(env, options, "currencyDisplay", map); 561 GetOptionValue(env, options, "unit", map); 562 GetOptionValue(env, options, "unitDisplay", map); 563 GetOptionValue(env, options, "compactDisplay", map); 564 GetOptionValue(env, options, "signDisplay", map); 565 GetOptionValue(env, options, "localeMatcher", map); 566 GetOptionValue(env, options, "style", map); 567 GetOptionValue(env, options, "numberingSystem", map); 568 GetOptionValue(env, options, "notation", map); 569 GetOptionValue(env, options, "unitUsage", map); 570 GetBoolOptionValue(env, options, "useGrouping", map); 571 GetIntegerOptionValue(env, options, "minimumIntegerDigits", map); 572 int64_t minFd = GetIntegerOptionValue(env, options, "minimumFractionDigits", map); 573 int64_t maxFd = GetIntegerOptionValue(env, options, "maximumFractionDigits", map); 574 if (minFd != -1 && maxFd != -1 && minFd > maxFd) { 575 HILOG_ERROR_I18N( 576 "GetNumberOptionValues: Invalid parameter value: minimumFractionDigits > maximumFractionDigits"); 577 } 578 GetIntegerOptionValue(env, options, "minimumSignificantDigits", map); 579 GetIntegerOptionValue(env, options, "maximumSignificantDigits", map); 580} 581 582napi_value IntlAddon::NumberFormatConstructor(napi_env env, napi_callback_info info) 583{ 584 size_t argc = 2; 585 napi_value argv[2] = { nullptr }; 586 napi_value thisVar = nullptr; 587 void *data = nullptr; 588 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 589 if (status != napi_ok) { 590 return nullptr; 591 } 592 std::vector<std::string> localeTags; 593 if (argc > 0) { 594 napi_valuetype valueType = napi_valuetype::napi_undefined; 595 napi_typeof(env, argv[0], &valueType); 596 bool isArray = false; 597 napi_is_array(env, argv[0], &isArray); 598 599 if (valueType == napi_valuetype::napi_string) { 600 GetLocaleTags(env, argv[0], localeTags); 601 } else if (isArray) { 602 uint32_t arrayLength = 0; 603 napi_get_array_length(env, argv[0], &arrayLength); 604 napi_value element = nullptr; 605 for (uint32_t i = 0; i < arrayLength; i++) { 606 napi_get_element(env, argv[0], i, &element); 607 GetLocaleTags(env, element, localeTags); 608 } 609 } 610 } 611 std::map<std::string, std::string> map = {}; 612 if (argc > 1) { 613 GetNumberOptionValues(env, argv[1], map); 614 } 615 std::unique_ptr<IntlAddon> obj = nullptr; 616 obj = std::make_unique<IntlAddon>(); 617 status = 618 napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), IntlAddon::Destructor, nullptr, nullptr); 619 if (status != napi_ok) { 620 HILOG_ERROR_I18N("NumberFormatConstructor: Wrap IntlAddon failed"); 621 return nullptr; 622 } 623 if (!obj->InitNumberFormatContext(env, info, localeTags, map)) { 624 HILOG_ERROR_I18N("Init NumberFormat failed"); 625 return nullptr; 626 } 627 obj.release(); 628 return thisVar; 629} 630 631bool IntlAddon::InitNumberFormatContext(napi_env env, napi_callback_info info, std::vector<std::string> localeTags, 632 std::map<std::string, std::string> &map) 633{ 634 napi_value global = nullptr; 635 napi_status status = napi_get_global(env, &global); 636 if (status != napi_ok) { 637 HILOG_ERROR_I18N("InitNumberFormatContext: Get global failed"); 638 return false; 639 } 640 env_ = env; 641 numberfmt_ = std::make_unique<NumberFormat>(localeTags, map); 642 643 return numberfmt_ != nullptr; 644} 645 646int64_t IntlAddon::GetMilliseconds(napi_env env, napi_value *argv, int index) 647{ 648 napi_value funcGetDateInfo = nullptr; 649 napi_status status = napi_get_named_property(env, argv[index], "getTime", &funcGetDateInfo); 650 if (status != napi_ok) { 651 HILOG_ERROR_I18N("Get Milliseconds property failed"); 652 return -1; 653 } 654 napi_value ret_value = nullptr; 655 status = napi_call_function(env, argv[index], funcGetDateInfo, 0, nullptr, &ret_value); 656 if (status != napi_ok) { 657 HILOG_ERROR_I18N("Get Milliseconds function failed"); 658 return -1; 659 } 660 int64_t milliseconds = 0; 661 status = napi_get_value_int64(env, ret_value, &milliseconds); 662 if (status != napi_ok) { 663 HILOG_ERROR_I18N("Get Milliseconds failed"); 664 return -1; 665 } 666 return milliseconds; 667} 668 669napi_value IntlAddon::GetLanguage(napi_env env, napi_callback_info info) 670{ 671 napi_value thisVar = nullptr; 672 void *data = nullptr; 673 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data); 674 675 IntlAddon *obj = nullptr; 676 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 677 if (status != napi_ok || !obj || !obj->locale_) { 678 HILOG_ERROR_I18N("GetLanguage: Get Locale object failed"); 679 return nullptr; 680 } 681 std::string value = obj->locale_->GetLanguage(); 682 683 napi_value result = nullptr; 684 status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result); 685 if (status != napi_ok) { 686 HILOG_ERROR_I18N("GetLanguage: Create language string failed"); 687 return nullptr; 688 } 689 return result; 690} 691 692napi_value IntlAddon::GetScript(napi_env env, napi_callback_info info) 693{ 694 napi_value thisVar = nullptr; 695 void *data = nullptr; 696 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data); 697 698 IntlAddon *obj = nullptr; 699 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 700 if (status != napi_ok || !obj || !obj->locale_) { 701 HILOG_ERROR_I18N("GetScript: Get Locale object failed"); 702 return nullptr; 703 } 704 std::string value = obj->locale_->GetScript(); 705 706 napi_value result = nullptr; 707 status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result); 708 if (status != napi_ok) { 709 HILOG_ERROR_I18N("Create script string failed"); 710 return nullptr; 711 } 712 return result; 713} 714 715napi_value IntlAddon::GetRegion(napi_env env, napi_callback_info info) 716{ 717 napi_value thisVar = nullptr; 718 void *data = nullptr; 719 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data); 720 721 IntlAddon *obj = nullptr; 722 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 723 if (status != napi_ok || !obj || !obj->locale_) { 724 HILOG_ERROR_I18N("GetRegion: Get Locale object failed"); 725 return nullptr; 726 } 727 std::string value = obj->locale_->GetRegion(); 728 729 napi_value result = nullptr; 730 status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result); 731 if (status != napi_ok) { 732 HILOG_ERROR_I18N("Create region string failed"); 733 return nullptr; 734 } 735 return result; 736} 737 738napi_value IntlAddon::GetBaseName(napi_env env, napi_callback_info info) 739{ 740 napi_value thisVar = nullptr; 741 void *data = nullptr; 742 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data); 743 744 IntlAddon *obj = nullptr; 745 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 746 if (status != napi_ok || !obj || !obj->locale_) { 747 HILOG_ERROR_I18N("GetBaseName: Get Locale object failed"); 748 return nullptr; 749 } 750 std::string value = obj->locale_->GetBaseName(); 751 752 napi_value result = nullptr; 753 status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result); 754 if (status != napi_ok) { 755 HILOG_ERROR_I18N("GetBaseName: Create base name string failed"); 756 return nullptr; 757 } 758 return result; 759} 760 761napi_value IntlAddon::GetCalendar(napi_env env, napi_callback_info info) 762{ 763 napi_value thisVar = nullptr; 764 void *data = nullptr; 765 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data); 766 767 IntlAddon *obj = nullptr; 768 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 769 if (status != napi_ok || !obj || !obj->locale_) { 770 HILOG_ERROR_I18N("GetCalendar: Get Locale object failed"); 771 return nullptr; 772 } 773 std::string value = obj->locale_->GetCalendar(); 774 775 napi_value result = nullptr; 776 status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result); 777 if (status != napi_ok) { 778 HILOG_ERROR_I18N("GetCalendar: Create base name string failed"); 779 return nullptr; 780 } 781 return result; 782} 783 784napi_value IntlAddon::GetCollation(napi_env env, napi_callback_info info) 785{ 786 napi_value thisVar = nullptr; 787 void *data = nullptr; 788 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data); 789 790 IntlAddon *obj = nullptr; 791 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 792 if (status != napi_ok || !obj || !obj->locale_) { 793 HILOG_ERROR_I18N("GetCollation: Get Locale object failed"); 794 return nullptr; 795 } 796 std::string value = obj->locale_->GetCollation(); 797 798 napi_value result = nullptr; 799 status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result); 800 if (status != napi_ok) { 801 HILOG_ERROR_I18N("GetCollation: Create base name string failed"); 802 return nullptr; 803 } 804 return result; 805} 806 807napi_value IntlAddon::GetHourCycle(napi_env env, napi_callback_info info) 808{ 809 napi_value thisVar = nullptr; 810 void *data = nullptr; 811 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data); 812 813 IntlAddon *obj = nullptr; 814 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 815 if (status != napi_ok || !obj || !obj->locale_) { 816 HILOG_ERROR_I18N("GetHourCycle: Get Locale object failed"); 817 return nullptr; 818 } 819 std::string value = obj->locale_->GetHourCycle(); 820 821 napi_value result = nullptr; 822 status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result); 823 if (status != napi_ok) { 824 HILOG_ERROR_I18N("GetHourCycle: Create base name string failed"); 825 return nullptr; 826 } 827 return result; 828} 829 830napi_value IntlAddon::GetNumberingSystem(napi_env env, napi_callback_info info) 831{ 832 napi_value thisVar = nullptr; 833 void *data = nullptr; 834 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data); 835 836 IntlAddon *obj = nullptr; 837 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 838 if (status != napi_ok || !obj || !obj->locale_) { 839 HILOG_ERROR_I18N("GetNumberingSystem: Get Locale object failed"); 840 return nullptr; 841 } 842 std::string value = obj->locale_->GetNumberingSystem(); 843 844 napi_value result = nullptr; 845 status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result); 846 if (status != napi_ok) { 847 HILOG_ERROR_I18N("GetNumberingSystem: Create base name string failed"); 848 return nullptr; 849 } 850 return result; 851} 852 853napi_value IntlAddon::GetNumeric(napi_env env, napi_callback_info info) 854{ 855 napi_value thisVar = nullptr; 856 void *data = nullptr; 857 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data); 858 859 IntlAddon *obj = nullptr; 860 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 861 if (status != napi_ok || !obj || !obj->locale_) { 862 HILOG_ERROR_I18N("GetNumeric: Get Locale object failed"); 863 return nullptr; 864 } 865 std::string value = obj->locale_->GetNumeric(); 866 bool optionBoolValue = (value == "true"); 867 napi_value result = nullptr; 868 status = napi_get_boolean(env, optionBoolValue, &result); 869 if (status != napi_ok) { 870 HILOG_ERROR_I18N("Create numeric boolean value failed"); 871 return nullptr; 872 } 873 return result; 874} 875 876napi_value IntlAddon::GetCaseFirst(napi_env env, napi_callback_info info) 877{ 878 napi_value thisVar = nullptr; 879 void *data = nullptr; 880 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data); 881 882 IntlAddon *obj = nullptr; 883 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 884 if (status != napi_ok || !obj || !obj->locale_) { 885 HILOG_ERROR_I18N("GetCaseFirst: Get Locale object failed"); 886 return nullptr; 887 } 888 std::string value = obj->locale_->GetCaseFirst(); 889 napi_value result = nullptr; 890 status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result); 891 if (status != napi_ok) { 892 HILOG_ERROR_I18N("Create caseFirst string failed"); 893 return nullptr; 894 } 895 return result; 896} 897 898napi_value IntlAddon::ToString(napi_env env, napi_callback_info info) 899{ 900 napi_value thisVar = nullptr; 901 void *data = nullptr; 902 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data); 903 904 IntlAddon *obj = nullptr; 905 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 906 if (status != napi_ok || !obj || !obj->locale_) { 907 HILOG_ERROR_I18N("ToString: Get Locale object failed"); 908 return nullptr; 909 } 910 std::string value = obj->locale_->ToString(); 911 912 napi_value result = nullptr; 913 status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result); 914 if (status != napi_ok) { 915 HILOG_ERROR_I18N("ToString: Create language string failed"); 916 return nullptr; 917 } 918 return result; 919} 920 921napi_value IntlAddon::Maximize(napi_env env, napi_callback_info info) 922{ 923 napi_value thisVar = nullptr; 924 void *data = nullptr; 925 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data); 926 927 IntlAddon *obj = nullptr; 928 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 929 if (status != napi_ok || !obj || !obj->locale_) { 930 HILOG_ERROR_I18N("Maximize: Get Locale object failed"); 931 return nullptr; 932 } 933 std::string localeTag = obj->locale_->Maximize(); 934 935 napi_value constructor = nullptr; 936 status = napi_get_reference_value(env, *g_constructor, &constructor); 937 if (status != napi_ok) { 938 HILOG_ERROR_I18N("Maximize: Get locale constructor reference failed"); 939 return nullptr; 940 } 941 napi_value result = nullptr; 942 napi_value arg = nullptr; 943 status = napi_create_string_utf8(env, localeTag.c_str(), NAPI_AUTO_LENGTH, &arg); 944 if (status != napi_ok) { 945 HILOG_ERROR_I18N("Maximize: Create localeTag string failed"); 946 return nullptr; 947 } 948 status = napi_new_instance(env, constructor, 1, &arg, &result); 949 if (status != napi_ok) { 950 HILOG_ERROR_I18N("Maximize: Create new locale instance failed"); 951 return nullptr; 952 } 953 return result; 954} 955 956napi_value IntlAddon::Minimize(napi_env env, napi_callback_info info) 957{ 958 napi_value thisVar = nullptr; 959 void *data = nullptr; 960 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data); 961 962 IntlAddon *obj = nullptr; 963 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 964 if (status != napi_ok || !obj || !obj->locale_) { 965 HILOG_ERROR_I18N("Minimize: Get Locale object failed"); 966 return nullptr; 967 } 968 std::string localeTag = obj->locale_->Minimize(); 969 970 napi_value constructor = nullptr; 971 status = napi_get_reference_value(env, *g_constructor, &constructor); 972 if (status != napi_ok) { 973 HILOG_ERROR_I18N("Minimize: Get locale constructor reference failed"); 974 return nullptr; 975 } 976 napi_value result = nullptr; 977 napi_value arg = nullptr; 978 status = napi_create_string_utf8(env, localeTag.c_str(), NAPI_AUTO_LENGTH, &arg); 979 if (status != napi_ok) { 980 HILOG_ERROR_I18N("Minimize: Create localeTag string failed"); 981 return nullptr; 982 } 983 status = napi_new_instance(env, constructor, 1, &arg, &result); 984 if (status != napi_ok) { 985 HILOG_ERROR_I18N("Minimize: Create new locale instance failed"); 986 return nullptr; 987 } 988 return result; 989} 990 991void SetOptionProperties(napi_env env, napi_value &result, std::map<std::string, std::string> &options, 992 const std::string &option) 993{ 994 if (options.count(option) > 0) { 995 std::string optionValue = options[option]; 996 napi_value optionJsValue = nullptr; 997 napi_create_string_utf8(env, optionValue.c_str(), NAPI_AUTO_LENGTH, &optionJsValue); 998 napi_set_named_property(env, result, option.c_str(), optionJsValue); 999 } else { 1000 napi_value undefined = nullptr; 1001 napi_get_undefined(env, &undefined); 1002 napi_set_named_property(env, result, option.c_str(), undefined); 1003 } 1004} 1005 1006void SetIntegerOptionProperties(napi_env env, napi_value &result, std::map<std::string, std::string> &options, 1007 const std::string &option) 1008{ 1009 if (options.count(option) > 0) { 1010 std::string optionValue = options[option]; 1011 napi_value optionJsValue = nullptr; 1012 int32_t status = 0; 1013 int64_t integerValue = ConvertString2Int(optionValue, status); 1014 if (status != -1) { 1015 napi_create_int64(env, integerValue, &optionJsValue); 1016 napi_set_named_property(env, result, option.c_str(), optionJsValue); 1017 return; 1018 } 1019 } 1020 napi_value undefined = nullptr; 1021 napi_get_undefined(env, &undefined); 1022 napi_set_named_property(env, result, option.c_str(), undefined); 1023} 1024 1025void SetBooleanOptionProperties(napi_env env, napi_value &result, std::map<std::string, std::string> &options, 1026 const std::string &option) 1027{ 1028 if (options.count(option) > 0) { 1029 std::string optionValue = options[option]; 1030 bool optionBoolValue = (optionValue == "true"); 1031 napi_value optionJsValue = nullptr; 1032 napi_get_boolean(env, optionBoolValue, &optionJsValue); 1033 napi_set_named_property(env, result, option.c_str(), optionJsValue); 1034 } else { 1035 napi_value undefined = nullptr; 1036 napi_get_undefined(env, &undefined); 1037 napi_set_named_property(env, result, option.c_str(), undefined); 1038 } 1039} 1040 1041napi_value IntlAddon::GetRelativeTimeResolvedOptions(napi_env env, napi_callback_info info) 1042{ 1043 napi_value thisVar = nullptr; 1044 void *data = nullptr; 1045 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data); 1046 1047 IntlAddon *obj = nullptr; 1048 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 1049 if (status != napi_ok || !obj || !obj->relativetimefmt_) { 1050 HILOG_ERROR_I18N("GetRelativeTimeResolvedOptions: Get RelativeTimeFormat object failed"); 1051 return nullptr; 1052 } 1053 napi_value result = nullptr; 1054 napi_create_object(env, &result); 1055 std::map<std::string, std::string> options = {}; 1056 obj->relativetimefmt_->GetResolvedOptions(options); 1057 SetOptionProperties(env, result, options, "locale"); 1058 SetOptionProperties(env, result, options, "style"); 1059 SetOptionProperties(env, result, options, "numeric"); 1060 SetOptionProperties(env, result, options, "numberingSystem"); 1061 return result; 1062} 1063 1064napi_value IntlAddon::GetDateTimeResolvedOptions(napi_env env, napi_callback_info info) 1065{ 1066 napi_value thisVar = nullptr; 1067 void *data = nullptr; 1068 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data); 1069 1070 IntlAddon *obj = nullptr; 1071 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 1072 if (status != napi_ok || !obj || !obj->datefmt_) { 1073 HILOG_ERROR_I18N("GetDateTimeResolvedOptions: Get DateTimeFormat object failed"); 1074 return nullptr; 1075 } 1076 napi_value result = nullptr; 1077 napi_create_object(env, &result); 1078 std::map<std::string, std::string> options = {}; 1079 obj->datefmt_->GetResolvedOptions(options); 1080 SetOptionProperties(env, result, options, "locale"); 1081 SetOptionProperties(env, result, options, "calendar"); 1082 SetOptionProperties(env, result, options, "dateStyle"); 1083 SetOptionProperties(env, result, options, "timeStyle"); 1084 SetOptionProperties(env, result, options, "hourCycle"); 1085 SetOptionProperties(env, result, options, "timeZone"); 1086 SetOptionProperties(env, result, options, "timeZoneName"); 1087 SetOptionProperties(env, result, options, "numberingSystem"); 1088 SetBooleanOptionProperties(env, result, options, "hour12"); 1089 SetOptionProperties(env, result, options, "weekday"); 1090 SetOptionProperties(env, result, options, "era"); 1091 SetOptionProperties(env, result, options, "year"); 1092 SetOptionProperties(env, result, options, "month"); 1093 SetOptionProperties(env, result, options, "day"); 1094 SetOptionProperties(env, result, options, "hour"); 1095 SetOptionProperties(env, result, options, "minute"); 1096 SetOptionProperties(env, result, options, "second"); 1097 SetOptionProperties(env, result, options, "dayPeriod"); 1098 SetOptionProperties(env, result, options, "localeMatcher"); 1099 SetOptionProperties(env, result, options, "formatMatcher"); 1100 return result; 1101} 1102 1103napi_value IntlAddon::GetNumberResolvedOptions(napi_env env, napi_callback_info info) 1104{ 1105 napi_value thisVar = nullptr; 1106 void *data = nullptr; 1107 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data); 1108 1109 IntlAddon *obj = nullptr; 1110 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 1111 if (status != napi_ok || !obj || !obj->numberfmt_) { 1112 HILOG_ERROR_I18N("GetNumberResolvedOptions: Get NumberFormat object failed"); 1113 return nullptr; 1114 } 1115 napi_value result = nullptr; 1116 napi_create_object(env, &result); 1117 std::map<std::string, std::string> options = {}; 1118 obj->numberfmt_->GetResolvedOptions(options); 1119 SetOptionProperties(env, result, options, "locale"); 1120 SetOptionProperties(env, result, options, "currency"); 1121 SetOptionProperties(env, result, options, "currencySign"); 1122 SetOptionProperties(env, result, options, "currencyDisplay"); 1123 SetOptionProperties(env, result, options, "unit"); 1124 SetOptionProperties(env, result, options, "unitDisplay"); 1125 SetOptionProperties(env, result, options, "signDisplay"); 1126 SetOptionProperties(env, result, options, "compactDisplay"); 1127 SetOptionProperties(env, result, options, "notation"); 1128 SetOptionProperties(env, result, options, "style"); 1129 SetOptionProperties(env, result, options, "numberingSystem"); 1130 SetOptionProperties(env, result, options, "unitUsage"); 1131 SetBooleanOptionProperties(env, result, options, "useGrouping"); 1132 SetIntegerOptionProperties(env, result, options, "minimumIntegerDigits"); 1133 SetIntegerOptionProperties(env, result, options, "minimumFractionDigits"); 1134 SetIntegerOptionProperties(env, result, options, "maximumFractionDigits"); 1135 SetIntegerOptionProperties(env, result, options, "minimumSignificantDigits"); 1136 SetIntegerOptionProperties(env, result, options, "maximumSignificantDigits"); 1137 SetOptionProperties(env, result, options, "localeMatcher"); 1138 return result; 1139} 1140 1141napi_value IntlAddon::FormatNumber(napi_env env, napi_callback_info info) 1142{ 1143 size_t argc = 1; 1144 napi_value argv[1] = { 0 }; 1145 napi_value thisVar = nullptr; 1146 void *data = nullptr; 1147 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 1148 double number = 0; 1149 napi_get_value_double(env, argv[0], &number); 1150 IntlAddon *obj = nullptr; 1151 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 1152 if (status != napi_ok || !obj || !obj->numberfmt_) { 1153 HILOG_ERROR_I18N("FormatNumber: Get NumberFormat object failed"); 1154 return nullptr; 1155 } 1156 std::string value = obj->numberfmt_->Format(number); 1157 napi_value result = nullptr; 1158 status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result); 1159 if (status != napi_ok) { 1160 HILOG_ERROR_I18N("FormatNumber: Create format string failed"); 1161 return nullptr; 1162 } 1163 return result; 1164} 1165 1166void GetCollatorLocaleMatcher(napi_env env, napi_value options, std::map<std::string, std::string> &map) 1167{ 1168 GetOptionValue(env, options, "localeMatcher", map); 1169 auto it = map.find("localeMatcher"); 1170 if (it != map.end()) { 1171 std::string localeMatcher = it->second; 1172 if (localeMatcher != "lookup" && localeMatcher != "best fit") { 1173 HILOG_ERROR_I18N("invalid localeMatcher"); 1174 return; 1175 } 1176 } else { 1177 map.insert(std::make_pair("localeMatcher", "best fit")); 1178 } 1179} 1180 1181void GetCollatorUsage(napi_env env, napi_value options, std::map<std::string, std::string> &map) 1182{ 1183 GetOptionValue(env, options, "usage", map); 1184 auto it = map.find("usage"); 1185 if (it != map.end()) { 1186 std::string usage = it->second; 1187 if (usage != "sort" && usage != "search") { 1188 HILOG_ERROR_I18N("invalid usage"); 1189 return; 1190 } 1191 } else { 1192 map.insert(std::make_pair("usage", "sort")); 1193 } 1194} 1195 1196void GetCollatorSensitivity(napi_env env, napi_value options, std::map<std::string, std::string> &map) 1197{ 1198 GetOptionValue(env, options, "sensitivity", map); 1199 auto it = map.find("sensitivity"); 1200 if (it != map.end()) { 1201 std::string sensitivity = it->second; 1202 if (sensitivity != "base" && sensitivity != "accent" && sensitivity != "case" && sensitivity != "variant") { 1203 HILOG_ERROR_I18N("invalid sensitivity"); 1204 return; 1205 } 1206 } else { 1207 map.insert(std::make_pair("sensitivity", "variant")); 1208 } 1209} 1210 1211void GetCollatorIgnorePunctuation(napi_env env, napi_value options, std::map<std::string, std::string> &map) 1212{ 1213 GetBoolOptionValue(env, options, "ignorePunctuation", map); 1214 auto it = map.find("ignorePunctuation"); 1215 if (it != map.end()) { 1216 std::string ignorePunctuation = it->second; 1217 if (ignorePunctuation != "true" && ignorePunctuation != "false") { 1218 HILOG_ERROR_I18N("invalid ignorePunctuation"); 1219 return; 1220 } 1221 } else { 1222 map.insert(std::make_pair("ignorePunctuation", "false")); 1223 } 1224} 1225 1226void GetCollatorNumeric(napi_env env, napi_value options, std::map<std::string, std::string> &map) 1227{ 1228 GetBoolOptionValue(env, options, "numeric", map); 1229 auto it = map.find("numeric"); 1230 if (it != map.end()) { 1231 std::string numeric = it->second; 1232 if (numeric != "true" && numeric != "false") { 1233 HILOG_ERROR_I18N("invalid numeric"); 1234 return; 1235 } 1236 } 1237} 1238 1239void GetCollatorCaseFirst(napi_env env, napi_value options, std::map<std::string, std::string> &map) 1240{ 1241 GetOptionValue(env, options, "caseFirst", map); 1242 auto it = map.find("caseFirst"); 1243 if (it != map.end()) { 1244 std::string caseFirst = it->second; 1245 if (caseFirst != "upper" && caseFirst != "lower" && caseFirst != "false") { 1246 HILOG_ERROR_I18N("invalid caseFirst"); 1247 return; 1248 } 1249 } 1250} 1251 1252void GetCollatorCollation(napi_env env, napi_value options, std::map<std::string, std::string> &map) 1253{ 1254 GetOptionValue(env, options, "collation", map); 1255 auto it = map.find("collation"); 1256 if (it != map.end()) { 1257 std::string collation = it->second; 1258 std::set<std::string> validCollation; 1259 validCollation.insert("big5han"); 1260 validCollation.insert("compat"); 1261 validCollation.insert("dict"); 1262 validCollation.insert("direct"); 1263 validCollation.insert("ducet"); 1264 validCollation.insert("eor"); 1265 validCollation.insert("gb2312"); 1266 validCollation.insert("phonebk"); 1267 validCollation.insert("phonetic"); 1268 validCollation.insert("pinyin"); 1269 validCollation.insert("reformed"); 1270 validCollation.insert("searchjl"); 1271 validCollation.insert("stroke"); 1272 validCollation.insert("trad"); 1273 validCollation.insert("unihan"); 1274 validCollation.insert("zhuyin"); 1275 if (validCollation.find(collation) == validCollation.end()) { 1276 map["collation"] = "default"; 1277 } 1278 } 1279} 1280 1281void GetCollatorOptionValue(napi_env env, napi_value options, std::map<std::string, std::string> &map) 1282{ 1283 GetCollatorLocaleMatcher(env, options, map); 1284 GetCollatorUsage(env, options, map); 1285 GetCollatorSensitivity(env, options, map); 1286 GetCollatorIgnorePunctuation(env, options, map); 1287 GetCollatorNumeric(env, options, map); 1288 GetCollatorCaseFirst(env, options, map); 1289 GetCollatorCollation(env, options, map); 1290} 1291 1292napi_value IntlAddon::InitCollator(napi_env env, napi_value exports) 1293{ 1294 napi_status status = napi_ok; 1295 napi_property_descriptor properties[] = { 1296 DECLARE_NAPI_FUNCTION("compare", CompareString), 1297 DECLARE_NAPI_FUNCTION("resolvedOptions", GetCollatorResolvedOptions) 1298 }; 1299 1300 napi_value constructor; 1301 status = napi_define_class(env, "Collator", NAPI_AUTO_LENGTH, CollatorConstructor, nullptr, 1302 sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor); 1303 if (status != napi_ok) { 1304 HILOG_ERROR_I18N("Define class failed when InitCollator"); 1305 return nullptr; 1306 } 1307 1308 status = napi_set_named_property(env, exports, "Collator", constructor); 1309 if (status != napi_ok) { 1310 HILOG_ERROR_I18N("Set property failed when InitCollator"); 1311 return nullptr; 1312 } 1313 return exports; 1314} 1315 1316napi_value IntlAddon::CollatorConstructor(napi_env env, napi_callback_info info) 1317{ 1318 size_t argc = 2; 1319 napi_value argv[2] = { nullptr }; 1320 napi_value thisVar = nullptr; 1321 void *data = nullptr; 1322 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 1323 if (status != napi_ok) { 1324 return nullptr; 1325 } 1326 std::vector<std::string> localeTags; 1327 if (argc > 0) { 1328 napi_valuetype valueType = napi_valuetype::napi_undefined; 1329 napi_typeof(env, argv[0], &valueType); 1330 bool isArray = false; 1331 napi_is_array(env, argv[0], &isArray); 1332 if (valueType == napi_valuetype::napi_string) { 1333 GetLocaleTags(env, argv[0], localeTags); 1334 } else if (isArray) { 1335 uint32_t arrayLength = 0; 1336 napi_get_array_length(env, argv[0], &arrayLength); 1337 napi_value element = nullptr; 1338 for (uint32_t i = 0; i < arrayLength; i++) { 1339 napi_get_element(env, argv[0], i, &element); 1340 GetLocaleTags(env, element, localeTags); 1341 } 1342 } 1343 } 1344 std::map<std::string, std::string> map = {}; 1345 if (argc > 1) { 1346 GetCollatorOptionValue(env, argv[1], map); 1347 } 1348 std::unique_ptr<IntlAddon> obj = nullptr; 1349 obj = std::make_unique<IntlAddon>(); 1350 status = 1351 napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), IntlAddon::Destructor, nullptr, nullptr); 1352 if (status != napi_ok) { 1353 HILOG_ERROR_I18N("CollatorConstructor: Wrap IntlAddon failed"); 1354 return nullptr; 1355 } 1356 if (!obj->InitCollatorContext(env, info, localeTags, map)) { 1357 HILOG_ERROR_I18N("CollatorConstructor: Init DateTimeFormat failed"); 1358 return nullptr; 1359 } 1360 obj.release(); 1361 return thisVar; 1362} 1363 1364bool IntlAddon::InitCollatorContext(napi_env env, napi_callback_info info, std::vector<std::string> localeTags, 1365 std::map<std::string, std::string> &map) 1366{ 1367 napi_value global = nullptr; 1368 napi_status status = napi_get_global(env, &global); 1369 if (status != napi_ok) { 1370 HILOG_ERROR_I18N("InitCollatorContext: Get global failed"); 1371 return false; 1372 } 1373 env_ = env; 1374 collator_ = std::make_unique<Collator>(localeTags, map); 1375 1376 return collator_ != nullptr; 1377} 1378 1379bool GetStringParameter(napi_env env, napi_value value, std::vector<char> &buf) 1380{ 1381 napi_valuetype valueType = napi_valuetype::napi_undefined; 1382 napi_typeof(env, value, &valueType); 1383 if (valueType != napi_valuetype::napi_string) { 1384 HILOG_ERROR_I18N("Parameter type does not match"); 1385 return false; 1386 } 1387 size_t len = 0; 1388 napi_status status = napi_get_value_string_utf8(env, value, nullptr, 0, &len); 1389 if (status != napi_ok) { 1390 HILOG_ERROR_I18N("Get first length failed"); 1391 return false; 1392 } 1393 buf.resize(len + 1); 1394 status = napi_get_value_string_utf8(env, value, buf.data(), len + 1, &len); 1395 if (status != napi_ok) { 1396 HILOG_ERROR_I18N("Get first failed"); 1397 return false; 1398 } 1399 1400 return true; 1401} 1402 1403napi_value IntlAddon::FormatRelativeTime(napi_env env, napi_callback_info info) 1404{ 1405 size_t argc = 2; 1406 napi_value argv[2] = { 0 }; 1407 napi_value thisVar = nullptr; 1408 void *data = nullptr; 1409 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 1410 napi_status status; 1411 double number; 1412 status = napi_get_value_double(env, argv[0], &number); 1413 if (status != napi_ok) { 1414 HILOG_ERROR_I18N("FormatRelativeTime: Get number failed"); 1415 return nullptr; 1416 } 1417 std::vector<char> unit; 1418 if (!GetStringParameter(env, argv[1], unit)) { 1419 return nullptr; 1420 } 1421 IntlAddon *obj = nullptr; 1422 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 1423 if (status != napi_ok || !obj || !obj->relativetimefmt_) { 1424 HILOG_ERROR_I18N("FormatRelativeTime: Get RelativeTimeFormat object failed"); 1425 return nullptr; 1426 } 1427 std::string value = obj->relativetimefmt_->Format(number, unit.data()); 1428 napi_value result = nullptr; 1429 status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result); 1430 if (status != napi_ok) { 1431 HILOG_ERROR_I18N("FormatRelativeTime: Create format string failed"); 1432 return nullptr; 1433 } 1434 return result; 1435} 1436 1437void IntlAddon::FillInArrayElement(napi_env env, napi_value &result, napi_status &status, 1438 const std::vector<std::vector<std::string>> &timeVector) 1439{ 1440 for (size_t i = 0; i < timeVector.size(); i++) { 1441 napi_value value = nullptr; 1442 status = napi_create_string_utf8(env, timeVector[i][1].c_str(), NAPI_AUTO_LENGTH, &value); 1443 if (status != napi_ok) { 1444 HILOG_ERROR_I18N("Failed to create string item imeVector[i][1]."); 1445 return; 1446 } 1447 napi_value type = nullptr; 1448 status = napi_create_string_utf8(env, timeVector[i][0].c_str(), NAPI_AUTO_LENGTH, &type); 1449 if (status != napi_ok) { 1450 HILOG_ERROR_I18N("Failed to create string item timeVector[i][0]."); 1451 return; 1452 } 1453 napi_value unit = nullptr; 1454 size_t unitIndex = 2; 1455 if (timeVector[i].size() > unitIndex) { 1456 status = napi_create_string_utf8(env, timeVector[i][unitIndex].c_str(), NAPI_AUTO_LENGTH, &unit); 1457 if (status != napi_ok) { 1458 HILOG_ERROR_I18N("Failed to create string item timeVector[i][unitIndex]."); 1459 return; 1460 } 1461 } else { 1462 napi_get_undefined(env, &unit); 1463 } 1464 napi_value formatInfo; 1465 status = napi_create_object(env, &formatInfo); 1466 if (status != napi_ok) { 1467 HILOG_ERROR_I18N("Failed to create format info object."); 1468 return; 1469 } 1470 napi_set_named_property(env, formatInfo, "type", type); 1471 napi_set_named_property(env, formatInfo, "value", value); 1472 napi_set_named_property(env, formatInfo, "unit", unit); 1473 status = napi_set_element(env, result, i, formatInfo); 1474 if (status != napi_ok) { 1475 HILOG_ERROR_I18N("Failed to set array item"); 1476 return; 1477 } 1478 } 1479} 1480 1481napi_value IntlAddon::FormatToParts(napi_env env, napi_callback_info info) 1482{ 1483 size_t argc = 2; 1484 napi_value argv[2] = { 0 }; 1485 napi_value thisVar = nullptr; 1486 void *data = nullptr; 1487 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 1488 double number = 0; 1489 napi_get_value_double(env, argv[0], &number); 1490 std::vector<char> unit; 1491 if (!GetStringParameter(env, argv[1], unit)) { 1492 return nullptr; 1493 } 1494 IntlAddon *obj = nullptr; 1495 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 1496 if (status != napi_ok || !obj || !obj->relativetimefmt_) { 1497 HILOG_ERROR_I18N("FormatToParts: Get RelativeTimeFormat object failed"); 1498 return nullptr; 1499 } 1500 std::vector<std::vector<std::string>> timeVector; 1501 obj->relativetimefmt_->FormatToParts(number, unit.data(), timeVector); 1502 napi_value result = nullptr; 1503 status = napi_create_array_with_length(env, timeVector.size(), &result); 1504 if (status != napi_ok) { 1505 HILOG_ERROR_I18N("Failed to create array"); 1506 return nullptr; 1507 } 1508 FillInArrayElement(env, result, status, timeVector); 1509 return result; 1510} 1511 1512napi_value IntlAddon::CompareString(napi_env env, napi_callback_info info) 1513{ 1514 size_t argc = 2; 1515 napi_value argv[2] = { 0 }; 1516 napi_value thisVar = nullptr; 1517 void *data = nullptr; 1518 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 1519 1520 std::vector<char> first; 1521 if (!GetStringParameter(env, argv[0], first)) { 1522 return nullptr; 1523 } 1524 1525 std::vector<char> second; 1526 if (!GetStringParameter(env, argv[1], second)) { 1527 return nullptr; 1528 } 1529 1530 IntlAddon *obj = nullptr; 1531 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 1532 if (status != napi_ok || !obj || !obj->collator_) { 1533 HILOG_ERROR_I18N("CompareString: Get Collator object failed"); 1534 return nullptr; 1535 } 1536 1537 CompareResult compareResult = obj->collator_->Compare(first.data(), second.data()); 1538 napi_value result = nullptr; 1539 status = napi_create_int32(env, compareResult, &result); 1540 if (status != napi_ok) { 1541 HILOG_ERROR_I18N("Create compare result failed"); 1542 return nullptr; 1543 } 1544 1545 return result; 1546} 1547 1548napi_value IntlAddon::GetCollatorResolvedOptions(napi_env env, napi_callback_info info) 1549{ 1550 napi_value thisVar = nullptr; 1551 void *data = nullptr; 1552 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data); 1553 1554 IntlAddon *obj = nullptr; 1555 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 1556 if (status != napi_ok || !obj || !obj->collator_) { 1557 HILOG_ERROR_I18N("GetCollatorResolvedOptions: Get Collator object failed"); 1558 return nullptr; 1559 } 1560 napi_value result = nullptr; 1561 napi_create_object(env, &result); 1562 std::map<std::string, std::string> options = {}; 1563 obj->collator_->ResolvedOptions(options); 1564 SetOptionProperties(env, result, options, "localeMatcher"); 1565 SetOptionProperties(env, result, options, "locale"); 1566 SetOptionProperties(env, result, options, "usage"); 1567 SetOptionProperties(env, result, options, "sensitivity"); 1568 SetBooleanOptionProperties(env, result, options, "ignorePunctuation"); 1569 SetBooleanOptionProperties(env, result, options, "numeric"); 1570 SetOptionProperties(env, result, options, "caseFirst"); 1571 SetOptionProperties(env, result, options, "collation"); 1572 return result; 1573} 1574 1575void GetPluralRulesType(napi_env env, napi_value options, std::map<std::string, std::string> &map) 1576{ 1577 GetOptionValue(env, options, "type", map); 1578 auto it = map.find("type"); 1579 if (it != map.end()) { 1580 std::string type = it->second; 1581 if (type != "cardinal" && type != "ordinal") { 1582 HILOG_ERROR_I18N("invalid type"); 1583 return; 1584 } 1585 } else { 1586 map.insert(std::make_pair("type", "cardinal")); 1587 } 1588} 1589 1590void GetPluralRulesInteger(napi_env env, napi_value options, std::map<std::string, std::string> &map) 1591{ 1592 GetIntegerOptionValue(env, options, "minimumIntegerDigits", map); 1593 auto it = map.find("minimumIntegerDigits"); 1594 if (it != map.end()) { 1595 std::string minimumIntegerDigits = it->second; 1596 int32_t status = 0; 1597 int n = ConvertString2Int(minimumIntegerDigits, status); 1598 if (status == -1 || n < 1 || n > 21) { // the valid range of minimumIntegerDigits is [1, 21] 1599 HILOG_ERROR_I18N("invalid minimumIntegerDigits"); 1600 return; 1601 } 1602 } else { 1603 map.insert(std::make_pair("minimumIntegerDigits", std::to_string(1))); 1604 } 1605} 1606 1607void GetPluralRulesFractions(napi_env env, napi_value options, std::map<std::string, std::string> &map) 1608{ 1609 GetIntegerOptionValue(env, options, "minimumFractionDigits", map); 1610 auto it = map.find("minimumFractionDigits"); 1611 if (it != map.end()) { 1612 std::string minimumFractionDigits = it->second; 1613 int32_t status = 0; 1614 int n = ConvertString2Int(minimumFractionDigits, status); 1615 if (status == -1 || n < 0 || n > 20) { // the valid range of minimumFractionDigits is [0, 20] 1616 HILOG_ERROR_I18N("invalid minimumFractionDigits"); 1617 return; 1618 } 1619 } 1620 1621 GetIntegerOptionValue(env, options, "maximumFractionDigits", map); 1622 it = map.find("maximumFractionDigits"); 1623 if (it != map.end()) { 1624 std::string maximumFractionDigits = it->second; 1625 int32_t status = 0; 1626 int n = ConvertString2Int(maximumFractionDigits, status); 1627 if (status == -1 || n < 0 || n > 20) { // the valid range of maximumFractionDigits is [0, 20] 1628 HILOG_ERROR_I18N("invalid maximumFractionDigits"); 1629 return; 1630 } 1631 } 1632} 1633 1634void GetPluralRulesSignificant(napi_env env, napi_value options, std::map<std::string, std::string> &map) 1635{ 1636 int minSignificant = -1; 1637 GetIntegerOptionValue(env, options, "minimumSignificantDigits", map); 1638 auto it = map.find("minimumSignificantDigits"); 1639 if (it != map.end()) { 1640 std::string minSignificantStr = it->second; 1641 int32_t status = 0; 1642 int minSignificantInt = ConvertString2Int(minSignificantStr, status); 1643 // the valid range of minSignificantInt is [1, 21] 1644 if (status == -1 || minSignificantInt < 1 || minSignificantInt > 21) { 1645 HILOG_ERROR_I18N("invalid minimumSignificantDigits"); 1646 return; 1647 } 1648 minSignificant = minSignificantInt; 1649 } else { 1650 minSignificant = 1; 1651 } 1652 1653 GetIntegerOptionValue(env, options, "maximumSignificantDigits", map); 1654 it = map.find("maximumSignificantDigits"); 1655 if (it != map.end()) { 1656 std::string maxSignificantStr = it->second; 1657 int32_t status = 0; 1658 int maxSignificant = ConvertString2Int(maxSignificantStr, status); 1659 // the valid range of minSignificant is [minSignificant, 21] 1660 if (status == -1 || maxSignificant < minSignificant || maxSignificant > 21) { 1661 HILOG_ERROR_I18N("invalid maximumSignificantDigits"); 1662 return; 1663 } 1664 } 1665} 1666 1667void GetPluralRulesOptionValues(napi_env env, napi_value options, std::map<std::string, std::string> &map) 1668{ 1669 GetCollatorLocaleMatcher(env, options, map); 1670 GetPluralRulesType(env, options, map); 1671 GetPluralRulesInteger(env, options, map); 1672 GetPluralRulesFractions(env, options, map); 1673 GetPluralRulesSignificant(env, options, map); 1674} 1675 1676napi_value IntlAddon::InitPluralRules(napi_env env, napi_value exports) 1677{ 1678 napi_status status = napi_ok; 1679 napi_property_descriptor properties[] = { 1680 DECLARE_NAPI_FUNCTION("select", Select) 1681 }; 1682 1683 napi_value constructor = nullptr; 1684 status = napi_define_class(env, "PluralRules", NAPI_AUTO_LENGTH, PluralRulesConstructor, nullptr, 1685 sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor); 1686 if (status != napi_ok) { 1687 HILOG_ERROR_I18N("Define class failed when InitPluralRules"); 1688 return nullptr; 1689 } 1690 1691 status = napi_set_named_property(env, exports, "PluralRules", constructor); 1692 if (status != napi_ok) { 1693 HILOG_ERROR_I18N("Set property failed when InitPluralRules"); 1694 return nullptr; 1695 } 1696 return exports; 1697} 1698 1699napi_value IntlAddon::PluralRulesConstructor(napi_env env, napi_callback_info info) 1700{ 1701 size_t argc = 2; 1702 napi_value argv[2] = { nullptr }; 1703 napi_value thisVar = nullptr; 1704 void *data = nullptr; 1705 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 1706 if (status != napi_ok) { 1707 return nullptr; 1708 } 1709 napi_valuetype valueType = napi_valuetype::napi_undefined; 1710 std::vector<std::string> localeTags; 1711 if (argc > 0) { 1712 napi_typeof(env, argv[0], &valueType); 1713 bool isArray = false; 1714 napi_is_array(env, argv[0], &isArray); 1715 if (valueType == napi_valuetype::napi_string) { 1716 GetLocaleTags(env, argv[0], localeTags); 1717 } else if (isArray) { 1718 uint32_t arrayLength = 0; 1719 napi_get_array_length(env, argv[0], &arrayLength); 1720 napi_value element = nullptr; 1721 for (uint32_t i = 0; i < arrayLength; i++) { 1722 napi_get_element(env, argv[0], i, &element); 1723 GetLocaleTags(env, element, localeTags); 1724 } 1725 } 1726 } 1727 std::map<std::string, std::string> map = {}; 1728 if (argc > 1) { 1729 GetPluralRulesOptionValues(env, argv[1], map); 1730 } 1731 std::unique_ptr<IntlAddon> obj = nullptr; 1732 obj = std::make_unique<IntlAddon>(); 1733 status = 1734 napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), IntlAddon::Destructor, nullptr, nullptr); 1735 if (status != napi_ok) { 1736 HILOG_ERROR_I18N("PluralRulesConstructor: Wrap IntlAddon failed"); 1737 return nullptr; 1738 } 1739 if (!obj->InitPluralRulesContext(env, info, localeTags, map)) { 1740 HILOG_ERROR_I18N("PluralRulesConstructor: Init DateTimeFormat failed"); 1741 return nullptr; 1742 } 1743 obj.release(); 1744 return thisVar; 1745} 1746 1747bool IntlAddon::InitPluralRulesContext(napi_env env, napi_callback_info info, std::vector<std::string> localeTags, 1748 std::map<std::string, std::string> &map) 1749{ 1750 napi_value global = nullptr; 1751 napi_status status = napi_get_global(env, &global); 1752 if (status != napi_ok) { 1753 HILOG_ERROR_I18N("InitPluralRulesContext: Get global failed"); 1754 return false; 1755 } 1756 env_ = env; 1757 pluralrules_ = std::make_unique<PluralRules>(localeTags, map); 1758 1759 return pluralrules_ != nullptr; 1760} 1761 1762napi_value IntlAddon::Select(napi_env env, napi_callback_info info) 1763{ 1764 size_t argc = 1; 1765 napi_value argv[1] = { 0 }; 1766 napi_value thisVar = nullptr; 1767 void *data = nullptr; 1768 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 1769 napi_valuetype valueType = napi_valuetype::napi_undefined; 1770 napi_typeof(env, argv[0], &valueType); 1771 if (valueType != napi_valuetype::napi_number) { 1772 HILOG_ERROR_I18N("Select: Parameter type does not match"); 1773 return nullptr; 1774 } 1775 1776 double number = 0; 1777 napi_status status = napi_get_value_double(env, argv[0], &number); 1778 if (status != napi_ok) { 1779 HILOG_ERROR_I18N("Select: Get number failed"); 1780 return nullptr; 1781 } 1782 1783 IntlAddon *obj = nullptr; 1784 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 1785 if (status != napi_ok || !obj || !obj->pluralrules_) { 1786 HILOG_ERROR_I18N("Get PluralRules object failed"); 1787 return nullptr; 1788 } 1789 1790 std::string res = obj->pluralrules_->Select(number); 1791 napi_value result = nullptr; 1792 status = napi_create_string_utf8(env, res.c_str(), NAPI_AUTO_LENGTH, &result); 1793 if (status != napi_ok) { 1794 HILOG_ERROR_I18N("get select result failed"); 1795 return nullptr; 1796 } 1797 return result; 1798} 1799 1800napi_value Init(napi_env env, napi_value exports) 1801{ 1802 napi_value val = IntlAddon::InitLocale(env, exports); 1803 val = IntlAddon::InitDateTimeFormat(env, val); 1804 val = IntlAddon::InitNumberFormat(env, val); 1805 val = IntlAddon::InitCollator(env, val); 1806 val = IntlAddon::InitRelativeTimeFormat(env, val); 1807 return IntlAddon::InitPluralRules(env, val); 1808} 1809 1810static napi_module g_intlModule = { 1811 .nm_version = 1, 1812 .nm_flags = 0, 1813 .nm_filename = nullptr, 1814 .nm_register_func = Init, 1815 .nm_modname = "intl", 1816 .nm_priv = nullptr, 1817 .reserved = { 0 } 1818}; 1819 1820extern "C" __attribute__((constructor)) void AbilityRegister() 1821{ 1822 napi_module_register(&g_intlModule); 1823} 1824} // namespace I18n 1825} // namespace Global 1826} // namespace OHOS 1827