14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#ifndef ECMASCRIPT_JSLOCALE_H 174514f5e3Sopenharmony_ci#define ECMASCRIPT_JSLOCALE_H 184514f5e3Sopenharmony_ci 194514f5e3Sopenharmony_ci#include "ecmascript/ecma_macros.h" 204514f5e3Sopenharmony_ci#include "ecmascript/js_array.h" 214514f5e3Sopenharmony_ci#include "ecmascript/js_object.h" 224514f5e3Sopenharmony_ci#include "ecmascript/js_thread.h" 234514f5e3Sopenharmony_ci#include "ecmascript/mem/c_containers.h" 244514f5e3Sopenharmony_ci 254514f5e3Sopenharmony_ci#include "ohos/init_data.h" 264514f5e3Sopenharmony_ci#include "unicode/basictz.h" 274514f5e3Sopenharmony_ci#include "unicode/brkiter.h" 284514f5e3Sopenharmony_ci#include "unicode/calendar.h" 294514f5e3Sopenharmony_ci#include "unicode/coll.h" 304514f5e3Sopenharmony_ci#include "unicode/datefmt.h" 314514f5e3Sopenharmony_ci#include "unicode/decimfmt.h" 324514f5e3Sopenharmony_ci#include "unicode/dtitvfmt.h" 334514f5e3Sopenharmony_ci#include "unicode/dtptngen.h" 344514f5e3Sopenharmony_ci#include "unicode/fieldpos.h" 354514f5e3Sopenharmony_ci#include "unicode/formattedvalue.h" 364514f5e3Sopenharmony_ci#include "unicode/gregocal.h" 374514f5e3Sopenharmony_ci#include "unicode/locid.h" 384514f5e3Sopenharmony_ci#include "unicode/normalizer2.h" 394514f5e3Sopenharmony_ci#include "unicode/numberformatter.h" 404514f5e3Sopenharmony_ci#include "unicode/numfmt.h" 414514f5e3Sopenharmony_ci#include "unicode/numsys.h" 424514f5e3Sopenharmony_ci#include "unicode/smpdtfmt.h" 434514f5e3Sopenharmony_ci#include "unicode/timezone.h" 444514f5e3Sopenharmony_ci#include "unicode/udat.h" 454514f5e3Sopenharmony_ci#include "unicode/unistr.h" 464514f5e3Sopenharmony_ci#include "unicode/ures.h" 474514f5e3Sopenharmony_ci#include "unicode/ustring.h" 484514f5e3Sopenharmony_ci#include "unicode/uvernum.h" 494514f5e3Sopenharmony_ci#include "unicode/uversion.h" 504514f5e3Sopenharmony_ci 514514f5e3Sopenharmony_cinamespace panda::ecmascript { 524514f5e3Sopenharmony_ci 534514f5e3Sopenharmony_cienum class OptionType : uint8_t { STRING = 0x01, BOOLEAN }; 544514f5e3Sopenharmony_cienum class LocaleMatcherOption : uint8_t { LOOKUP = 0x01, BEST_FIT, EXCEPTION }; 554514f5e3Sopenharmony_cienum class FormatMatcherOption : uint8_t { BASIC = 0x01, BEST_FIT, EXCEPTION }; 564514f5e3Sopenharmony_cienum class LocaleType : uint8_t { 574514f5e3Sopenharmony_ci LITERAL = 0x01, 584514f5e3Sopenharmony_ci NUMBER, 594514f5e3Sopenharmony_ci PLUS_SIGN, 604514f5e3Sopenharmony_ci MINUS_SIGN, 614514f5e3Sopenharmony_ci PERCENT_SIGN, 624514f5e3Sopenharmony_ci UNIT_PREFIX, 634514f5e3Sopenharmony_ci UNIT_SUFFIX, 644514f5e3Sopenharmony_ci CURRENCY_CODE, 654514f5e3Sopenharmony_ci CURRENCY_PREFIX, 664514f5e3Sopenharmony_ci CURRENCY_SUFFIX, 674514f5e3Sopenharmony_ci}; 684514f5e3Sopenharmony_ci 694514f5e3Sopenharmony_cienum class TypeOption : uint8_t { CARDINAL = 0x01, ORDINAL, EXCEPTION }; 704514f5e3Sopenharmony_cienum class RoundingType : uint8_t { FRACTIONDIGITS = 0x01, SIGNIFICANTDIGITS, COMPACTROUNDING, EXCEPTION }; 714514f5e3Sopenharmony_cienum class NotationOption : uint8_t { STANDARD = 0x01, SCIENTIFIC, ENGINEERING, COMPACT, EXCEPTION }; 724514f5e3Sopenharmony_ci 734514f5e3Sopenharmony_ciconstexpr uint32_t MAX_DIGITS = 21; 744514f5e3Sopenharmony_ciconstexpr uint32_t MAX_FRACTION_DIGITS = 20; 754514f5e3Sopenharmony_ciconstexpr uint8_t INTL_INDEX_ZERO = 0; 764514f5e3Sopenharmony_ciconstexpr uint8_t INTL_INDEX_ONE = 1; 774514f5e3Sopenharmony_ciconstexpr uint8_t INTL_INDEX_TWO = 2; 784514f5e3Sopenharmony_ciconstexpr uint8_t INTL_INDEX_THREE = 3; 794514f5e3Sopenharmony_ciconstexpr uint8_t INTL_INDEX_FOUR = 4; 804514f5e3Sopenharmony_ciconstexpr uint8_t INTL_INDEX_FIVE = 5; 814514f5e3Sopenharmony_ciconstexpr uint8_t INTL_INDEX_EIGHT = 8; 824514f5e3Sopenharmony_ci 834514f5e3Sopenharmony_ciclass JSIntlIterator : public icu::Locale::Iterator { 844514f5e3Sopenharmony_cipublic: 854514f5e3Sopenharmony_ci JSIntlIterator(const JSHandle<TaggedArray> &data, uint32_t length) : length_(length), curIdx_(0) 864514f5e3Sopenharmony_ci { 874514f5e3Sopenharmony_ci for (uint32_t idx = 0; idx < length; idx++) { 884514f5e3Sopenharmony_ci auto itor = data->Get(idx); 894514f5e3Sopenharmony_ci std::string str = EcmaStringAccessor(itor).ToStdString(); 904514f5e3Sopenharmony_ci data_.emplace_back(str); 914514f5e3Sopenharmony_ci } 924514f5e3Sopenharmony_ci } 934514f5e3Sopenharmony_ci 944514f5e3Sopenharmony_ci ~JSIntlIterator() override = default; 954514f5e3Sopenharmony_ci DEFAULT_COPY_SEMANTIC(JSIntlIterator); 964514f5e3Sopenharmony_ci DEFAULT_MOVE_SEMANTIC(JSIntlIterator); 974514f5e3Sopenharmony_ci 984514f5e3Sopenharmony_ci UBool hasNext() const override 994514f5e3Sopenharmony_ci { 1004514f5e3Sopenharmony_ci return static_cast<UBool>(curIdx_ < length_); 1014514f5e3Sopenharmony_ci } 1024514f5e3Sopenharmony_ci 1034514f5e3Sopenharmony_ci const icu::Locale &next() override 1044514f5e3Sopenharmony_ci { 1054514f5e3Sopenharmony_ci ASSERT(curIdx_ < length_); 1064514f5e3Sopenharmony_ci UErrorCode status = U_ZERO_ERROR; 1074514f5e3Sopenharmony_ci locale_ = icu::Locale::forLanguageTag(data_[curIdx_].c_str(), status); 1084514f5e3Sopenharmony_ci ASSERT(U_SUCCESS(status)); 1094514f5e3Sopenharmony_ci curIdx_++; 1104514f5e3Sopenharmony_ci return locale_; 1114514f5e3Sopenharmony_ci } 1124514f5e3Sopenharmony_ci 1134514f5e3Sopenharmony_ci inline const std::string &operator[](size_t index) const noexcept 1144514f5e3Sopenharmony_ci { 1154514f5e3Sopenharmony_ci ASSERT(index < length_); 1164514f5e3Sopenharmony_ci return data_[index]; 1174514f5e3Sopenharmony_ci } 1184514f5e3Sopenharmony_ci 1194514f5e3Sopenharmony_ciprivate: 1204514f5e3Sopenharmony_ci std::vector<std::string> data_{}; 1214514f5e3Sopenharmony_ci uint32_t length_{0}; 1224514f5e3Sopenharmony_ci uint32_t curIdx_{0}; 1234514f5e3Sopenharmony_ci icu::Locale locale_{}; 1244514f5e3Sopenharmony_ci}; 1254514f5e3Sopenharmony_ci 1264514f5e3Sopenharmony_cistruct ResolvedLocale { 1274514f5e3Sopenharmony_ci std::string locale {}; 1284514f5e3Sopenharmony_ci icu::Locale localeData {}; 1294514f5e3Sopenharmony_ci std::map<std::string, std::string> extensions {}; 1304514f5e3Sopenharmony_ci}; 1314514f5e3Sopenharmony_ci 1324514f5e3Sopenharmony_cistruct MatcherResult { 1334514f5e3Sopenharmony_ci std::string locale; 1344514f5e3Sopenharmony_ci std::string extension; 1354514f5e3Sopenharmony_ci}; 1364514f5e3Sopenharmony_ci 1374514f5e3Sopenharmony_cistruct OptionData { 1384514f5e3Sopenharmony_ci std::string name; 1394514f5e3Sopenharmony_ci std::string key; 1404514f5e3Sopenharmony_ci std::vector<std::string> possibleValues; 1414514f5e3Sopenharmony_ci bool isBoolValue = false; 1424514f5e3Sopenharmony_ci}; 1434514f5e3Sopenharmony_ci 1444514f5e3Sopenharmony_cistruct TagElements { 1454514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> language; 1464514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> script; 1474514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> region; 1484514f5e3Sopenharmony_ci}; 1494514f5e3Sopenharmony_ci 1504514f5e3Sopenharmony_ciclass JSLocale : public JSObject { 1514514f5e3Sopenharmony_cipublic: 1524514f5e3Sopenharmony_ci static const std::set<std::string> WELL_NUMBER_SYSTEM; 1534514f5e3Sopenharmony_ci static const std::set<std::string> WELL_COLLATION; 1544514f5e3Sopenharmony_ci 1554514f5e3Sopenharmony_ci static const std::string LATN_STRING; 1564514f5e3Sopenharmony_ci 1574514f5e3Sopenharmony_ci static const std::vector<LocaleMatcherOption> LOCALE_MATCHER_OPTION; 1584514f5e3Sopenharmony_ci static const std::vector<std::string> LOCALE_MATCHER_OPTION_NAME; 1594514f5e3Sopenharmony_ci 1604514f5e3Sopenharmony_ci static const std::map<std::string, std::set<std::string>> LOCALE_MAP; 1614514f5e3Sopenharmony_ci 1624514f5e3Sopenharmony_ci static const std::vector<std::string> HOUR_CYCLE; 1634514f5e3Sopenharmony_ci static const std::vector<std::string> CASE_FIRST; 1644514f5e3Sopenharmony_ci static JSLocale *Cast(TaggedObject *object) 1654514f5e3Sopenharmony_ci { 1664514f5e3Sopenharmony_ci ASSERT(JSTaggedValue(object).IsJSLocale()); 1674514f5e3Sopenharmony_ci return static_cast<JSLocale *>(object); 1684514f5e3Sopenharmony_ci } 1694514f5e3Sopenharmony_ci 1704514f5e3Sopenharmony_ci static constexpr size_t ICU_FIELD_OFFSET = JSObject::SIZE; 1714514f5e3Sopenharmony_ci // icu::Locale internal slot. 1724514f5e3Sopenharmony_ci ACCESSORS(IcuField, ICU_FIELD_OFFSET, SIZE) 1734514f5e3Sopenharmony_ci 1744514f5e3Sopenharmony_ci DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, ICU_FIELD_OFFSET, SIZE) 1754514f5e3Sopenharmony_ci DECL_DUMP() 1764514f5e3Sopenharmony_ci 1774514f5e3Sopenharmony_ci icu::Locale *GetIcuLocale() const 1784514f5e3Sopenharmony_ci { 1794514f5e3Sopenharmony_ci ASSERT(GetIcuField().IsJSNativePointer()); 1804514f5e3Sopenharmony_ci auto result = JSNativePointer::Cast(GetIcuField().GetTaggedObject())->GetExternalPointer(); 1814514f5e3Sopenharmony_ci return reinterpret_cast<icu::Locale *>(result); 1824514f5e3Sopenharmony_ci } 1834514f5e3Sopenharmony_ci 1844514f5e3Sopenharmony_ci static void FreeIcuLocale([[maybe_unused]] void *env, void *pointer, void *data) 1854514f5e3Sopenharmony_ci { 1864514f5e3Sopenharmony_ci if (pointer == nullptr) { 1874514f5e3Sopenharmony_ci return; 1884514f5e3Sopenharmony_ci } 1894514f5e3Sopenharmony_ci auto icuLocale = reinterpret_cast<icu::Locale *>(pointer); 1904514f5e3Sopenharmony_ci icuLocale->~Locale(); 1914514f5e3Sopenharmony_ci if (data != nullptr) { 1924514f5e3Sopenharmony_ci reinterpret_cast<EcmaVM *>(data)->GetNativeAreaAllocator()->FreeBuffer(pointer); 1934514f5e3Sopenharmony_ci } 1944514f5e3Sopenharmony_ci } 1954514f5e3Sopenharmony_ci 1964514f5e3Sopenharmony_ci // 6.2.4 DefaultLocale () 1974514f5e3Sopenharmony_ci static JSHandle<EcmaString> DefaultLocale(JSThread *thread); 1984514f5e3Sopenharmony_ci 1994514f5e3Sopenharmony_ci // 6.4.1 IsValidTimeZoneName ( timeZone ) 2004514f5e3Sopenharmony_ci static bool IsValidTimeZoneName(const icu::TimeZone &tz); 2014514f5e3Sopenharmony_ci 2024514f5e3Sopenharmony_ci // 9.2.3 LookupMatcher ( availableLocales, requestedLocales ) 2034514f5e3Sopenharmony_ci static JSHandle<EcmaString> LookupMatcher(JSThread *thread, const JSHandle<TaggedArray> &availableLocales, 2044514f5e3Sopenharmony_ci const JSHandle<TaggedArray> &requestedLocales); 2054514f5e3Sopenharmony_ci 2064514f5e3Sopenharmony_ci // 9.2.4 BestFitMatcher ( availableLocales, requestedLocales ) 2074514f5e3Sopenharmony_ci static JSHandle<EcmaString> BestFitMatcher(JSThread *thread, const JSHandle<TaggedArray> &availableLocales, 2084514f5e3Sopenharmony_ci const JSHandle<TaggedArray> &requestedLocales); 2094514f5e3Sopenharmony_ci 2104514f5e3Sopenharmony_ci // 9.2.5 UnicodeExtensionValue ( extension, key ) 2114514f5e3Sopenharmony_ci static std::string UnicodeExtensionValue(const std::string extension, const std::string key); 2124514f5e3Sopenharmony_ci 2134514f5e3Sopenharmony_ci // 9.2.7 ResolveLocale ( availableLocales, requestedLocales, options, relevantExtensionKeys, localeData ) 2144514f5e3Sopenharmony_ci static ResolvedLocale ResolveLocale(JSThread *thread, const JSHandle<TaggedArray> &availableLocales, 2154514f5e3Sopenharmony_ci const JSHandle<TaggedArray> &requestedLocales, 2164514f5e3Sopenharmony_ci [[maybe_unused]] LocaleMatcherOption matcher, 2174514f5e3Sopenharmony_ci const std::set<std::string> &relevantExtensionKeys); 2184514f5e3Sopenharmony_ci 2194514f5e3Sopenharmony_ci // 9.2.8 LookupSupportedLocales ( availableLocales, requestedLocales ) 2204514f5e3Sopenharmony_ci static JSHandle<TaggedArray> LookupSupportedLocales(JSThread *thread, const JSHandle<TaggedArray> &availableLocales, 2214514f5e3Sopenharmony_ci const JSHandle<TaggedArray> &requestedLocales); 2224514f5e3Sopenharmony_ci 2234514f5e3Sopenharmony_ci // 9.2.9 BestFitSupportedLocales ( availableLocales, requestedLocales ) 2244514f5e3Sopenharmony_ci static JSHandle<TaggedArray> BestFitSupportedLocales(JSThread *thread, 2254514f5e3Sopenharmony_ci const JSHandle<TaggedArray> &availableLocales, 2264514f5e3Sopenharmony_ci const JSHandle<TaggedArray> &requestedLocales); 2274514f5e3Sopenharmony_ci 2284514f5e3Sopenharmony_ci // 9.2.10 SupportedLocales ( availableLocales, requestedLocales, options ) 2294514f5e3Sopenharmony_ci static JSHandle<JSArray> SupportedLocales(JSThread *thread, const JSHandle<TaggedArray> &availableLocales, 2304514f5e3Sopenharmony_ci const JSHandle<TaggedArray> &requestedLocales, 2314514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &options); 2324514f5e3Sopenharmony_ci 2334514f5e3Sopenharmony_ci // 9.2.11 GetOption ( options, property, type, values, fallback ) 2344514f5e3Sopenharmony_ci template<typename T> 2354514f5e3Sopenharmony_ci static T GetOptionOfString(JSThread *thread, const JSHandle<JSObject> &options, 2364514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &property, const std::vector<T> &enumValues, 2374514f5e3Sopenharmony_ci const std::vector<std::string> &strValues, T fallback) 2384514f5e3Sopenharmony_ci { 2394514f5e3Sopenharmony_ci // 1. Let value be ? Get(options, property). 2404514f5e3Sopenharmony_ci OperationResult operationResult = JSObject::GetProperty(thread, options, property); 2414514f5e3Sopenharmony_ci RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, T::EXCEPTION); 2424514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> value = operationResult.GetValue(); 2434514f5e3Sopenharmony_ci 2444514f5e3Sopenharmony_ci if (value->IsUndefined()) { 2454514f5e3Sopenharmony_ci return fallback; 2464514f5e3Sopenharmony_ci } 2474514f5e3Sopenharmony_ci 2484514f5e3Sopenharmony_ci // 2. If value is not undefined, then 2494514f5e3Sopenharmony_ci // d. If values is not undefined, then 2504514f5e3Sopenharmony_ci // i. If values does not contain an element equal to value, throw a RangeError exception. 2514514f5e3Sopenharmony_ci JSHandle<EcmaString> valueEStr = JSTaggedValue::ToString(thread, value); 2524514f5e3Sopenharmony_ci RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, T::EXCEPTION); 2534514f5e3Sopenharmony_ci std::string valueStr = std::string(ConvertToString(*valueEStr, StringConvertedUsage::LOGICOPERATION)); 2544514f5e3Sopenharmony_ci int existIdx = -1; 2554514f5e3Sopenharmony_ci if (!enumValues.empty()) { 2564514f5e3Sopenharmony_ci size_t strValuesSize = strValues.size(); 2574514f5e3Sopenharmony_ci for (size_t i = 0; i < strValuesSize; i++) { 2584514f5e3Sopenharmony_ci if (strValues[i] == valueStr) { 2594514f5e3Sopenharmony_ci existIdx = static_cast<int>(i); 2604514f5e3Sopenharmony_ci } 2614514f5e3Sopenharmony_ci } 2624514f5e3Sopenharmony_ci if (existIdx == -1) { 2634514f5e3Sopenharmony_ci THROW_RANGE_ERROR_AND_RETURN(thread, "getStringOption failed", T::EXCEPTION); 2644514f5e3Sopenharmony_ci } 2654514f5e3Sopenharmony_ci } 2664514f5e3Sopenharmony_ci if (existIdx == -1) { 2674514f5e3Sopenharmony_ci LOG_ECMA(FATAL) << "this branch is unreachable"; 2684514f5e3Sopenharmony_ci UNREACHABLE(); 2694514f5e3Sopenharmony_ci } 2704514f5e3Sopenharmony_ci // e.Return value. 2714514f5e3Sopenharmony_ci return enumValues[existIdx]; 2724514f5e3Sopenharmony_ci } 2734514f5e3Sopenharmony_ci 2744514f5e3Sopenharmony_ci static bool GetOptionOfBool(JSThread *thread, const JSHandle<JSObject> &options, 2754514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &property, bool fallback, bool *res); 2764514f5e3Sopenharmony_ci 2774514f5e3Sopenharmony_ci static JSHandle<JSTaggedValue> GetOption(JSThread *thread, const JSHandle<JSObject> &options, 2784514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &property, OptionType type, 2794514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &values, 2804514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &fallback); 2814514f5e3Sopenharmony_ci 2824514f5e3Sopenharmony_ci static bool GetOptionOfString(JSThread *thread, const JSHandle<JSObject> &options, 2834514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &property, const std::vector<std::string> &values, 2844514f5e3Sopenharmony_ci std::string *optionValue); 2854514f5e3Sopenharmony_ci 2864514f5e3Sopenharmony_ci // 9.2.12 DefaultNumberOption ( value, minimum, maximum, fallback ) 2874514f5e3Sopenharmony_ci static int DefaultNumberOption(JSThread *thread, const JSHandle<JSTaggedValue> &value, int minimum, int maximum, 2884514f5e3Sopenharmony_ci int fallback); 2894514f5e3Sopenharmony_ci 2904514f5e3Sopenharmony_ci // 9.2.13 GetNumberOption ( options, property, minimum, maximum, fallback ) 2914514f5e3Sopenharmony_ci static int GetNumberOption(JSThread *thread, const JSHandle<JSObject> &options, 2924514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &property, int minimum, int maximum, int fallback); 2934514f5e3Sopenharmony_ci 2944514f5e3Sopenharmony_ci static bool IsLanguageSubtag(const std::string &value) 2954514f5e3Sopenharmony_ci { 2964514f5e3Sopenharmony_ci return IsAlpha(value, INTL_INDEX_TWO, INTL_INDEX_THREE) || IsAlpha(value, INTL_INDEX_FIVE, INTL_INDEX_EIGHT); 2974514f5e3Sopenharmony_ci } 2984514f5e3Sopenharmony_ci 2994514f5e3Sopenharmony_ci static bool IsScriptSubtag(const std::string &value) 3004514f5e3Sopenharmony_ci { 3014514f5e3Sopenharmony_ci return IsAlpha(value, INTL_INDEX_FOUR, INTL_INDEX_FOUR); 3024514f5e3Sopenharmony_ci } 3034514f5e3Sopenharmony_ci 3044514f5e3Sopenharmony_ci static bool IsRegionSubtag(const std::string &value) 3054514f5e3Sopenharmony_ci { 3064514f5e3Sopenharmony_ci return IsAlpha(value, INTL_INDEX_TWO, INTL_INDEX_TWO) || IsDigit(value, INTL_INDEX_THREE, INTL_INDEX_THREE); 3074514f5e3Sopenharmony_ci } 3084514f5e3Sopenharmony_ci 3094514f5e3Sopenharmony_ci static bool IsVariantSubtag(const std::string &value) 3104514f5e3Sopenharmony_ci { 3114514f5e3Sopenharmony_ci return IsThirdDigitAlphanum(value) || IsAlphanum(value, INTL_INDEX_FIVE, INTL_INDEX_EIGHT); 3124514f5e3Sopenharmony_ci } 3134514f5e3Sopenharmony_ci 3144514f5e3Sopenharmony_ci static bool IsThirdDigitAlphanum(const std::string &value) 3154514f5e3Sopenharmony_ci { 3164514f5e3Sopenharmony_ci return InRange(value[0], '0', '9') && value.length() == INTL_INDEX_FOUR && 3174514f5e3Sopenharmony_ci IsAlphanum(value.substr(INTL_INDEX_ONE), INTL_INDEX_THREE, INTL_INDEX_THREE); 3184514f5e3Sopenharmony_ci } 3194514f5e3Sopenharmony_ci 3204514f5e3Sopenharmony_ci static bool IsExtensionSingleton(const std::string &value) 3214514f5e3Sopenharmony_ci { 3224514f5e3Sopenharmony_ci return IsAlphanum(value, INTL_INDEX_ONE, INTL_INDEX_ONE); 3234514f5e3Sopenharmony_ci } 3244514f5e3Sopenharmony_ci 3254514f5e3Sopenharmony_ci static bool IsNormativeCalendar(const std::string &value) 3264514f5e3Sopenharmony_ci { 3274514f5e3Sopenharmony_ci return IsWellAlphaNumList(value); 3284514f5e3Sopenharmony_ci } 3294514f5e3Sopenharmony_ci 3304514f5e3Sopenharmony_ci static bool IsNormativeNumberingSystem(const std::string &value) 3314514f5e3Sopenharmony_ci { 3324514f5e3Sopenharmony_ci return IsWellAlphaNumList(value); 3334514f5e3Sopenharmony_ci } 3344514f5e3Sopenharmony_ci 3354514f5e3Sopenharmony_ci static bool IsWellNumberingSystem(const std::string &value) 3364514f5e3Sopenharmony_ci { 3374514f5e3Sopenharmony_ci if (JSLocale::WELL_NUMBER_SYSTEM.find(value) != JSLocale::WELL_NUMBER_SYSTEM.end()) { 3384514f5e3Sopenharmony_ci return false; 3394514f5e3Sopenharmony_ci } 3404514f5e3Sopenharmony_ci UErrorCode status = U_ZERO_ERROR; 3414514f5e3Sopenharmony_ci icu::NumberingSystem *numberingSystem = icu::NumberingSystem::createInstanceByName(value.c_str(), status); 3424514f5e3Sopenharmony_ci bool result = U_SUCCESS(status) != 0 && numberingSystem != nullptr; 3434514f5e3Sopenharmony_ci delete numberingSystem; 3444514f5e3Sopenharmony_ci numberingSystem = nullptr; 3454514f5e3Sopenharmony_ci return result; 3464514f5e3Sopenharmony_ci } 3474514f5e3Sopenharmony_ci 3484514f5e3Sopenharmony_ci static bool IsWellCollation(const icu::Locale &locale, const std::string &value) 3494514f5e3Sopenharmony_ci { 3504514f5e3Sopenharmony_ci if (JSLocale::WELL_COLLATION.find(value) != JSLocale::WELL_COLLATION.end()) { 3514514f5e3Sopenharmony_ci return false; 3524514f5e3Sopenharmony_ci } 3534514f5e3Sopenharmony_ci return IsWellExtension<icu::Collator>(locale, "collation", value); 3544514f5e3Sopenharmony_ci } 3554514f5e3Sopenharmony_ci 3564514f5e3Sopenharmony_ci static bool IsWellCalendar(const icu::Locale &locale, const std::string &value) 3574514f5e3Sopenharmony_ci { 3584514f5e3Sopenharmony_ci return IsWellExtension<icu::Calendar>(locale, "calendar", value); 3594514f5e3Sopenharmony_ci } 3604514f5e3Sopenharmony_ci 3614514f5e3Sopenharmony_ci template<typename T> 3624514f5e3Sopenharmony_ci static bool IsWellExtension(const icu::Locale &locale, const char *key, const std::string &value) 3634514f5e3Sopenharmony_ci { 3644514f5e3Sopenharmony_ci UErrorCode status = U_ZERO_ERROR; 3654514f5e3Sopenharmony_ci const char *outdatedType = uloc_toLegacyType(key, value.c_str()); 3664514f5e3Sopenharmony_ci if (outdatedType == nullptr) { 3674514f5e3Sopenharmony_ci return false; 3684514f5e3Sopenharmony_ci } 3694514f5e3Sopenharmony_ci icu::StringEnumeration *sequence = T::getKeywordValuesForLocale(key, icu::Locale(locale.getBaseName()), 3704514f5e3Sopenharmony_ci false, status); 3714514f5e3Sopenharmony_ci if (U_FAILURE(status)) { 3724514f5e3Sopenharmony_ci delete sequence; 3734514f5e3Sopenharmony_ci sequence = nullptr; 3744514f5e3Sopenharmony_ci return false; 3754514f5e3Sopenharmony_ci } 3764514f5e3Sopenharmony_ci int32_t size = 0; 3774514f5e3Sopenharmony_ci const char *element = sequence->next(&size, status); 3784514f5e3Sopenharmony_ci while (U_SUCCESS(status) && element != nullptr) { 3794514f5e3Sopenharmony_ci if (strcmp(outdatedType, element) == 0) { 3804514f5e3Sopenharmony_ci delete sequence; 3814514f5e3Sopenharmony_ci sequence = nullptr; 3824514f5e3Sopenharmony_ci return true; 3834514f5e3Sopenharmony_ci } 3844514f5e3Sopenharmony_ci element = sequence->next(&size, status); 3854514f5e3Sopenharmony_ci } 3864514f5e3Sopenharmony_ci delete sequence; 3874514f5e3Sopenharmony_ci sequence = nullptr; 3884514f5e3Sopenharmony_ci return false; 3894514f5e3Sopenharmony_ci } 3904514f5e3Sopenharmony_ci 3914514f5e3Sopenharmony_ci static inline constexpr int AsciiAlphaToLower(uint32_t c) 3924514f5e3Sopenharmony_ci { 3934514f5e3Sopenharmony_ci constexpr uint32_t FLAG = 0x20; 3944514f5e3Sopenharmony_ci return static_cast<int>(c | FLAG); 3954514f5e3Sopenharmony_ci } 3964514f5e3Sopenharmony_ci 3974514f5e3Sopenharmony_ci static bool IsAsciiAlpha(char ch) 3984514f5e3Sopenharmony_ci { 3994514f5e3Sopenharmony_ci return InRange(ch, 'A', 'Z') || InRange(ch, 'a', 'z'); 4004514f5e3Sopenharmony_ci } 4014514f5e3Sopenharmony_ci 4024514f5e3Sopenharmony_ci static char LocaleIndependentAsciiToUpper(char ch) 4034514f5e3Sopenharmony_ci { 4044514f5e3Sopenharmony_ci return (InRange(ch, 'a', 'z')) ? static_cast<char>((ch - 'a' + 'A')) : ch; 4054514f5e3Sopenharmony_ci } 4064514f5e3Sopenharmony_ci 4074514f5e3Sopenharmony_ci static char LocaleIndependentAsciiToLower(char ch) 4084514f5e3Sopenharmony_ci { 4094514f5e3Sopenharmony_ci return (InRange(ch, 'A', 'Z')) ? static_cast<char>((ch - 'A' + 'a')) : ch; 4104514f5e3Sopenharmony_ci } 4114514f5e3Sopenharmony_ci 4124514f5e3Sopenharmony_ci template<typename T, typename U> 4134514f5e3Sopenharmony_ci static bool InRange(T value, U start, U end) 4144514f5e3Sopenharmony_ci { 4154514f5e3Sopenharmony_ci ASSERT(start <= end); 4164514f5e3Sopenharmony_ci ASSERT(sizeof(T) >= sizeof(U)); 4174514f5e3Sopenharmony_ci return (value >= static_cast<T>(start)) && (value <= static_cast<T>(end)); 4184514f5e3Sopenharmony_ci } 4194514f5e3Sopenharmony_ci 4204514f5e3Sopenharmony_ci static bool IsWellAlphaNumList(const std::string &value) 4214514f5e3Sopenharmony_ci { 4224514f5e3Sopenharmony_ci if (value.length() < INTL_INDEX_THREE) { 4234514f5e3Sopenharmony_ci return false; 4244514f5e3Sopenharmony_ci } 4254514f5e3Sopenharmony_ci char lastChar = value[value.length() - 1]; 4264514f5e3Sopenharmony_ci if (lastChar == '-') { 4274514f5e3Sopenharmony_ci return false; 4284514f5e3Sopenharmony_ci } 4294514f5e3Sopenharmony_ci std::vector<std::string> items; 4304514f5e3Sopenharmony_ci std::istringstream input(value); 4314514f5e3Sopenharmony_ci std::string temp; 4324514f5e3Sopenharmony_ci while (getline(input, temp, '-')) { 4334514f5e3Sopenharmony_ci items.push_back(temp); 4344514f5e3Sopenharmony_ci } 4354514f5e3Sopenharmony_ci for (auto &item : items) { 4364514f5e3Sopenharmony_ci if (!IsAlphanum(item, INTL_INDEX_THREE, INTL_INDEX_EIGHT)) { 4374514f5e3Sopenharmony_ci return false; 4384514f5e3Sopenharmony_ci } 4394514f5e3Sopenharmony_ci } 4404514f5e3Sopenharmony_ci return true; 4414514f5e3Sopenharmony_ci } 4424514f5e3Sopenharmony_ci 4434514f5e3Sopenharmony_ci static bool ValidateOtherTags(const icu::Locale &locale, const char *packageName, const char *key, bool &res) 4444514f5e3Sopenharmony_ci { 4454514f5e3Sopenharmony_ci const char *localeCountry = locale.getCountry(); 4464514f5e3Sopenharmony_ci const char *localeScript = locale.getScript(); 4474514f5e3Sopenharmony_ci std::string removeCountry; 4484514f5e3Sopenharmony_ci if (localeCountry[0] != '\0' && localeScript[0] != '\0') { 4494514f5e3Sopenharmony_ci removeCountry = locale.getLanguage(); 4504514f5e3Sopenharmony_ci removeCountry.append("-"); 4514514f5e3Sopenharmony_ci removeCountry.append(localeScript); 4524514f5e3Sopenharmony_ci return CheckLocales(removeCountry.c_str(), key, packageName, res); 4534514f5e3Sopenharmony_ci } 4544514f5e3Sopenharmony_ci if (localeCountry[0] != '\0' || localeScript[0] != '\0') { 4554514f5e3Sopenharmony_ci std::string language = locale.getLanguage(); 4564514f5e3Sopenharmony_ci return CheckLocales(language.c_str(), key, packageName, res); 4574514f5e3Sopenharmony_ci } 4584514f5e3Sopenharmony_ci return res; 4594514f5e3Sopenharmony_ci } 4604514f5e3Sopenharmony_ci 4614514f5e3Sopenharmony_ci static bool CheckLocales(const icu::Locale &locale, const char *key, const char *packageName, bool &res) 4624514f5e3Sopenharmony_ci { 4634514f5e3Sopenharmony_ci res = false; 4644514f5e3Sopenharmony_ci UErrorCode status = U_ZERO_ERROR; 4654514f5e3Sopenharmony_ci const char *formalLocale = locale.getName(); 4664514f5e3Sopenharmony_ci UResourceBundle *localeRes = ures_open(packageName, formalLocale, &status); 4674514f5e3Sopenharmony_ci if (localeRes != nullptr && status == U_ZERO_ERROR) { 4684514f5e3Sopenharmony_ci if (key == nullptr) { 4694514f5e3Sopenharmony_ci res = true; 4704514f5e3Sopenharmony_ci } else { 4714514f5e3Sopenharmony_ci UResourceBundle *keyRes = ures_getByKey(localeRes, key, nullptr, &status); 4724514f5e3Sopenharmony_ci if (keyRes != nullptr && status == U_ZERO_ERROR) { 4734514f5e3Sopenharmony_ci res = true; 4744514f5e3Sopenharmony_ci } 4754514f5e3Sopenharmony_ci ures_close(keyRes); 4764514f5e3Sopenharmony_ci } 4774514f5e3Sopenharmony_ci } 4784514f5e3Sopenharmony_ci ures_close(localeRes); 4794514f5e3Sopenharmony_ci if (res) { 4804514f5e3Sopenharmony_ci return res; 4814514f5e3Sopenharmony_ci } else { 4824514f5e3Sopenharmony_ci ValidateOtherTags(locale, packageName, key, res); 4834514f5e3Sopenharmony_ci } 4844514f5e3Sopenharmony_ci return res; 4854514f5e3Sopenharmony_ci } 4864514f5e3Sopenharmony_ci 4874514f5e3Sopenharmony_ci static std::vector<std::string> GetAvailableStringLocales(JSThread *thread, 4884514f5e3Sopenharmony_ci const JSHandle<TaggedArray> &availableLocales); 4894514f5e3Sopenharmony_ci 4904514f5e3Sopenharmony_ci static JSHandle<JSObject> PutElement(JSThread *thread, int index, const JSHandle<JSArray> &array, 4914514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &fieldTypeString, 4924514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &value); 4934514f5e3Sopenharmony_ci 4944514f5e3Sopenharmony_ci static std::string GetNumberingSystem(const icu::Locale &icuLocale); 4954514f5e3Sopenharmony_ci 4964514f5e3Sopenharmony_ci static bool IsWellFormedCurrencyCode(const std::string ¤cy); 4974514f5e3Sopenharmony_ci 4984514f5e3Sopenharmony_ci static bool IsWellFormedCalendarCode(const std::string& calendar); 4994514f5e3Sopenharmony_ci 5004514f5e3Sopenharmony_ci static JSHandle<JSTaggedValue> GetNumberFieldType(JSThread *thread, JSTaggedValue x, int32_t fieldId); 5014514f5e3Sopenharmony_ci 5024514f5e3Sopenharmony_ci static bool ApplyOptionsToTag(JSThread *thread, const JSHandle<EcmaString> &tag, const JSHandle<JSObject> &options, 5034514f5e3Sopenharmony_ci TagElements &tagElements); 5044514f5e3Sopenharmony_ci 5054514f5e3Sopenharmony_ci static JSHandle<JSLocale> InitializeLocale(JSThread *thread, const JSHandle<JSLocale> &locale, 5064514f5e3Sopenharmony_ci const JSHandle<EcmaString> &localeString, 5074514f5e3Sopenharmony_ci const JSHandle<JSObject> &options); 5084514f5e3Sopenharmony_ci 5094514f5e3Sopenharmony_ci static JSTaggedValue NormalizeKeywordValue(JSThread *thread, const JSHandle<JSLocale> &locale, 5104514f5e3Sopenharmony_ci const std::string &key); 5114514f5e3Sopenharmony_ci 5124514f5e3Sopenharmony_ci static JSHandle<EcmaString> ToString(JSThread *thread, const JSHandle<JSLocale> &locale); 5134514f5e3Sopenharmony_ci 5144514f5e3Sopenharmony_ci // 12.1.1 SetNumberFormatDigitOptions ( intlObj, options, mnfdDefault, mxfdDefault, notation ) 5154514f5e3Sopenharmony_ci template<typename T> 5164514f5e3Sopenharmony_ci static void SetNumberFormatDigitOptions(JSThread *thread, const JSHandle<T> &intlObj, 5174514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &options, int mnfdDefault, int mxfdDefault, 5184514f5e3Sopenharmony_ci NotationOption notation) 5194514f5e3Sopenharmony_ci { 5204514f5e3Sopenharmony_ci // 1. Assert: Type(intlObj) is Object. 5214514f5e3Sopenharmony_ci // 2. Assert: Type(options) is Object. 5224514f5e3Sopenharmony_ci // 3. Assert: Type(mnfdDefault) is Number. 5234514f5e3Sopenharmony_ci // 4. Assert: Type(mxfdDefault) is Number. 5244514f5e3Sopenharmony_ci ASSERT(options->IsHeapObject()); 5254514f5e3Sopenharmony_ci auto globalConst = thread->GlobalConstants(); 5264514f5e3Sopenharmony_ci // Set intlObj.[[MinimumFractionDigits]] to 0. 5274514f5e3Sopenharmony_ci intlObj->SetMinimumFractionDigits(thread, JSTaggedValue(0)); 5284514f5e3Sopenharmony_ci // Set intlObj.[[MaximumFractionDigits]] to 0. 5294514f5e3Sopenharmony_ci intlObj->SetMaximumFractionDigits(thread, JSTaggedValue(0)); 5304514f5e3Sopenharmony_ci // Set intlObj.[[MinimumSignificantDigits]] to 0. 5314514f5e3Sopenharmony_ci intlObj->SetMinimumSignificantDigits(thread, JSTaggedValue(0)); 5324514f5e3Sopenharmony_ci // Set intlObj.[[MaximumSignificantDigits]] to 0. 5334514f5e3Sopenharmony_ci intlObj->SetMaximumSignificantDigits(thread, JSTaggedValue(0)); 5344514f5e3Sopenharmony_ci 5354514f5e3Sopenharmony_ci // 5. Let mnid be ? GetNumberOption(options, "minimumIntegerDigits,", 1, 21, 1). 5364514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> mnidKey = globalConst->GetHandledMinimumIntegerDigitsString(); 5374514f5e3Sopenharmony_ci int mnid = GetNumberOption(thread, JSHandle<JSObject>::Cast(options), mnidKey, 1, MAX_DIGITS, 1); 5384514f5e3Sopenharmony_ci // 6. Let mnfd be ? Get(options, "minimumFractionDigits"). 5394514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> mnfdKey = globalConst->GetHandledMinimumFractionDigitsString(); 5404514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> mnfd = JSTaggedValue::GetProperty(thread, options, mnfdKey).GetValue(); 5414514f5e3Sopenharmony_ci intlObj->SetMinimumIntegerDigits(thread, JSTaggedValue(mnid)); 5424514f5e3Sopenharmony_ci RETURN_IF_ABRUPT_COMPLETION(thread); 5434514f5e3Sopenharmony_ci // 7. Let mxfd be ? Get(options, "maximumFractionDigits"). 5444514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> mxfdKey = globalConst->GetHandledMaximumFractionDigitsString(); 5454514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> mxfd = JSTaggedValue::GetProperty(thread, options, mxfdKey).GetValue(); 5464514f5e3Sopenharmony_ci RETURN_IF_ABRUPT_COMPLETION(thread); 5474514f5e3Sopenharmony_ci // 8. Let mnsd be ? Get(options, "minimumSignificantDigits"). 5484514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> mnsdKey = globalConst->GetHandledMinimumSignificantDigitsString(); 5494514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> mnsd = JSTaggedValue::GetProperty(thread, options, mnsdKey).GetValue(); 5504514f5e3Sopenharmony_ci RETURN_IF_ABRUPT_COMPLETION(thread); 5514514f5e3Sopenharmony_ci // 9. Let mxsd be ? Get(options, "maximumSignificantDigits"). 5524514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> mxsdKey = globalConst->GetHandledMaximumSignificantDigitsString(); 5534514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> mxsd = JSTaggedValue::GetProperty(thread, options, mxsdKey).GetValue(); 5544514f5e3Sopenharmony_ci RETURN_IF_ABRUPT_COMPLETION(thread); 5554514f5e3Sopenharmony_ci 5564514f5e3Sopenharmony_ci // 10. Set intlObj.[[MinimumIntegerDigits]] to mnid. 5574514f5e3Sopenharmony_ci // 11. If mnsd is not undefined or mxsd is not undefined, then 5584514f5e3Sopenharmony_ci if (!mnsd->IsUndefined() || !mxsd->IsUndefined()) { 5594514f5e3Sopenharmony_ci // a. Set intlObj.[[RoundingType]] to significantDigits. 5604514f5e3Sopenharmony_ci intlObj->SetRoundingType(RoundingType::SIGNIFICANTDIGITS); 5614514f5e3Sopenharmony_ci // b. Let mnsd be ? DefaultNumberOption(mnsd, 1, 21, 1). 5624514f5e3Sopenharmony_ci mnsd = JSHandle<JSTaggedValue>( 5634514f5e3Sopenharmony_ci thread, JSTaggedValue(JSLocale::DefaultNumberOption(thread, mnsd, 1, MAX_DIGITS, 1))); 5644514f5e3Sopenharmony_ci RETURN_IF_ABRUPT_COMPLETION(thread); 5654514f5e3Sopenharmony_ci // c. Let mxsd be ? DefaultNumberOption(mxsd, mnsd, 21, 21). 5664514f5e3Sopenharmony_ci mxsd = JSHandle<JSTaggedValue>(thread, 5674514f5e3Sopenharmony_ci JSTaggedValue(JSLocale::DefaultNumberOption(thread, mxsd, mnsd->GetInt(), MAX_DIGITS, MAX_DIGITS))); 5684514f5e3Sopenharmony_ci RETURN_IF_ABRUPT_COMPLETION(thread); 5694514f5e3Sopenharmony_ci // d. Set intlObj.[[MinimumSignificantDigits]] to mnsd. 5704514f5e3Sopenharmony_ci intlObj->SetMinimumSignificantDigits(thread, mnsd); 5714514f5e3Sopenharmony_ci // e. Set intlObj.[[MaximumSignificantDigits]] to mxsd. 5724514f5e3Sopenharmony_ci intlObj->SetMaximumSignificantDigits(thread, mxsd); 5734514f5e3Sopenharmony_ci } else { 5744514f5e3Sopenharmony_ci if (!mnfd->IsUndefined() || !mxfd->IsUndefined()) { 5754514f5e3Sopenharmony_ci // 12. Else if mnfd is not undefined or mxfd is not undefined, then 5764514f5e3Sopenharmony_ci // a. Set intlObj.[[RoundingType]] to fractionDigits. 5774514f5e3Sopenharmony_ci intlObj->SetRoundingType(RoundingType::FRACTIONDIGITS); 5784514f5e3Sopenharmony_ci if (!mxfd->IsUndefined()) { 5794514f5e3Sopenharmony_ci JSTaggedValue mxfdValue = 5804514f5e3Sopenharmony_ci JSTaggedValue(JSLocale::DefaultNumberOption(thread, mxfd, 0, MAX_FRACTION_DIGITS, mxfdDefault)); 5814514f5e3Sopenharmony_ci RETURN_IF_ABRUPT_COMPLETION(thread); 5824514f5e3Sopenharmony_ci mxfd = JSHandle<JSTaggedValue>(thread, mxfdValue); 5834514f5e3Sopenharmony_ci mnfdDefault = std::min(mnfdDefault, mxfd->GetInt()); 5844514f5e3Sopenharmony_ci } 5854514f5e3Sopenharmony_ci // b. Let mnfd be ? DefaultNumberOption(mnfd, 0, 20, mnfdDefault). 5864514f5e3Sopenharmony_ci mnfd = JSHandle<JSTaggedValue>( 5874514f5e3Sopenharmony_ci thread, JSTaggedValue(DefaultNumberOption(thread, mnfd, 0, MAX_FRACTION_DIGITS, mnfdDefault))); 5884514f5e3Sopenharmony_ci // c. Let mxfdActualDefault be max( mnfd, mxfdDefault ). 5894514f5e3Sopenharmony_ci int mxfdActualDefault = std::max(mnfd->GetInt(), mxfdDefault); 5904514f5e3Sopenharmony_ci // d. Let mxfd be ? DefaultNumberOption(mxfd, mnfd, 20, mxfdActualDefault). 5914514f5e3Sopenharmony_ci mxfd = JSHandle<JSTaggedValue>( 5924514f5e3Sopenharmony_ci thread, JSTaggedValue(JSLocale::DefaultNumberOption(thread, mxfd, mnfd->GetInt(), 5934514f5e3Sopenharmony_ci MAX_FRACTION_DIGITS, mxfdActualDefault))); 5944514f5e3Sopenharmony_ci RETURN_IF_ABRUPT_COMPLETION(thread); 5954514f5e3Sopenharmony_ci // e. Set intlObj.[[MinimumFractionDigits]] to mnfd. 5964514f5e3Sopenharmony_ci intlObj->SetMinimumFractionDigits(thread, mnfd); 5974514f5e3Sopenharmony_ci // f. Set intlObj.[[MaximumFractionDigits]] to mxfd. 5984514f5e3Sopenharmony_ci intlObj->SetMaximumFractionDigits(thread, mxfd); 5994514f5e3Sopenharmony_ci } else if (notation == NotationOption::COMPACT) { 6004514f5e3Sopenharmony_ci // 13. Else if notation is "compact", then 6014514f5e3Sopenharmony_ci // a. Set intlObj.[[RoundingType]] to compactRounding. 6024514f5e3Sopenharmony_ci intlObj->SetRoundingType(RoundingType::COMPACTROUNDING); 6034514f5e3Sopenharmony_ci } else { 6044514f5e3Sopenharmony_ci // 14. else, 6054514f5e3Sopenharmony_ci // a.Set intlObj.[[RoundingType]] to fractionDigits. 6064514f5e3Sopenharmony_ci intlObj->SetRoundingType(RoundingType::FRACTIONDIGITS); 6074514f5e3Sopenharmony_ci // b.Set intlObj.[[MinimumFractionDigits]] to mnfdDefault. 6084514f5e3Sopenharmony_ci intlObj->SetMinimumFractionDigits(thread, JSTaggedValue(mnfdDefault)); 6094514f5e3Sopenharmony_ci // c.Set intlObj.[[MaximumFractionDigits]] to mxfdDefault. 6104514f5e3Sopenharmony_ci intlObj->SetMaximumFractionDigits(thread, JSTaggedValue(mxfdDefault)); 6114514f5e3Sopenharmony_ci } 6124514f5e3Sopenharmony_ci } 6134514f5e3Sopenharmony_ci } 6144514f5e3Sopenharmony_ci 6154514f5e3Sopenharmony_ci static JSHandle<TaggedArray> ConstructLocaleList(JSThread *thread, 6164514f5e3Sopenharmony_ci const std::vector<std::string> &icuAvailableLocales); 6174514f5e3Sopenharmony_ci 6184514f5e3Sopenharmony_ci static bool CheckLocales(const icu::Locale &locale, const char *path, const char *key); 6194514f5e3Sopenharmony_ci 6204514f5e3Sopenharmony_ci static bool IsPrivateSubTag(std::string result, size_t len) 6214514f5e3Sopenharmony_ci { 6224514f5e3Sopenharmony_ci if ((len > INTL_INDEX_ONE) && (result[INTL_INDEX_ONE] == '-')) { 6234514f5e3Sopenharmony_ci ASSERT(result[INTL_INDEX_ZERO] == 'x' || result[INTL_INDEX_ZERO] == 'i'); 6244514f5e3Sopenharmony_ci return true; 6254514f5e3Sopenharmony_ci } 6264514f5e3Sopenharmony_ci return false; 6274514f5e3Sopenharmony_ci } 6284514f5e3Sopenharmony_ci 6294514f5e3Sopenharmony_ciprivate: 6304514f5e3Sopenharmony_ci static icu::Locale BuildICULocale(const std::string &bcp47Locale); 6314514f5e3Sopenharmony_ci 6324514f5e3Sopenharmony_ci static bool IsCheckRange(const std::string &str, size_t min, size_t max, bool(rangeCheckFunc)(char)) 6334514f5e3Sopenharmony_ci { 6344514f5e3Sopenharmony_ci if (!InRange(str.length(), min, max)) { 6354514f5e3Sopenharmony_ci return false; 6364514f5e3Sopenharmony_ci } 6374514f5e3Sopenharmony_ci for (char i : str) { 6384514f5e3Sopenharmony_ci if (!rangeCheckFunc(i)) { 6394514f5e3Sopenharmony_ci return false; 6404514f5e3Sopenharmony_ci } 6414514f5e3Sopenharmony_ci } 6424514f5e3Sopenharmony_ci return true; 6434514f5e3Sopenharmony_ci } 6444514f5e3Sopenharmony_ci 6454514f5e3Sopenharmony_ci static bool IsAlpha(const std::string &str, size_t min, size_t max) 6464514f5e3Sopenharmony_ci { 6474514f5e3Sopenharmony_ci if (!InRange(str.length(), min, max)) { 6484514f5e3Sopenharmony_ci return false; 6494514f5e3Sopenharmony_ci } 6504514f5e3Sopenharmony_ci for (char c : str) { 6514514f5e3Sopenharmony_ci if (!IsAsciiAlpha(c)) { 6524514f5e3Sopenharmony_ci return false; 6534514f5e3Sopenharmony_ci } 6544514f5e3Sopenharmony_ci } 6554514f5e3Sopenharmony_ci return true; 6564514f5e3Sopenharmony_ci } 6574514f5e3Sopenharmony_ci 6584514f5e3Sopenharmony_ci static bool IsDigit(const std::string &str, size_t min, size_t max) 6594514f5e3Sopenharmony_ci { 6604514f5e3Sopenharmony_ci if (!InRange(str.length(), min, max)) { 6614514f5e3Sopenharmony_ci return false; 6624514f5e3Sopenharmony_ci } 6634514f5e3Sopenharmony_ci for (char i : str) { 6644514f5e3Sopenharmony_ci if (!InRange(i, '0', '9')) { 6654514f5e3Sopenharmony_ci return false; 6664514f5e3Sopenharmony_ci } 6674514f5e3Sopenharmony_ci } 6684514f5e3Sopenharmony_ci return true; 6694514f5e3Sopenharmony_ci } 6704514f5e3Sopenharmony_ci 6714514f5e3Sopenharmony_ci static bool IsAlphanum(const std::string &str, size_t min, size_t max) 6724514f5e3Sopenharmony_ci { 6734514f5e3Sopenharmony_ci if (!InRange(str.length(), min, max)) { 6744514f5e3Sopenharmony_ci return false; 6754514f5e3Sopenharmony_ci } 6764514f5e3Sopenharmony_ci for (char i : str) { 6774514f5e3Sopenharmony_ci if (!IsAsciiAlpha(i) && !InRange(i, '0', '9')) { 6784514f5e3Sopenharmony_ci return false; 6794514f5e3Sopenharmony_ci } 6804514f5e3Sopenharmony_ci } 6814514f5e3Sopenharmony_ci return true; 6824514f5e3Sopenharmony_ci } 6834514f5e3Sopenharmony_ci 6844514f5e3Sopenharmony_ci static bool IsAToZ(char ch) 6854514f5e3Sopenharmony_ci { 6864514f5e3Sopenharmony_ci int lowerCh = JSLocale::AsciiAlphaToLower(ch); 6874514f5e3Sopenharmony_ci return JSLocale::InRange(lowerCh, 'a', 'z'); 6884514f5e3Sopenharmony_ci } 6894514f5e3Sopenharmony_ci}; 6904514f5e3Sopenharmony_ci} // namespace panda::ecmascript 6914514f5e3Sopenharmony_ci#endif // ECMASCRIPT_JSLOCALE_H 692