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 &currency);
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