parsedate解析月份,月份静态常量提取,优化时间解析

Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IAMPWY

Signed-off-by: jiangmengyang <jiangmengyang3@huawei.com>
Change-Id: Ib03f02d99d4de4742b0c3c89558fcef87a2ef188
This commit is contained in:
jiangmengyang 2024-08-30 16:22:11 +08:00
parent 76ae8ff357
commit 1119d6a746
10 changed files with 261 additions and 73 deletions

View File

@ -16,6 +16,10 @@
#include "ecmascript/date_parse.h"
namespace panda::ecmascript {
const std::array<CString, MOUTH_PER_YEAR> DateParse::MONTH_NAME = {
"jan", "feb", "mar", "apr", "may", "jun",
"jul", "aug", "sep", "oct", "nov", "dec"
};
bool DateParse::ParseDateString(const char *str, int length, int *time)
{
StringReader reader(str, length);
@ -327,12 +331,8 @@ DateParse::DateValueType DateParse::DateProxy::MatchKeyWord(const CString &str,
*value = 1;
return DATE_TIME_ZONE;
}
std::array<CString, MOUTH_PER_YEAR> monthName = {
"jan", "feb", "mar", "apr", "may", "jun",
"jul", "aug", "sep", "oct", "nov", "dec"
};
for (int i = 0; i < MOUTH_PER_YEAR; i++) {
if (str == monthName[i]) {
if (str == DateParse::MONTH_NAME[i]) {
*value = i + 1;
return DATE_MONTH;
}

View File

@ -21,6 +21,7 @@
namespace panda::ecmascript {
class DateParse {
public:
static const std::array<CString, MOUTH_PER_YEAR> MONTH_NAME;
static bool ParseDateString(const char *str, int length, int *time);
private:

View File

@ -33,6 +33,34 @@ const std::map<CaseFirstOption, UColAttributeValue> JSCollator::uColAttributeVal
{CaseFirstOption::FALSE_OPTION, UCOL_OFF},
{CaseFirstOption::UNDEFINED, UCOL_OFF}
};
const std::vector<LocaleMatcherOption> JSCollator::LOCALE_MATCHER_OPTION = {
LocaleMatcherOption::LOOKUP, LocaleMatcherOption::BEST_FIT
};
const std::vector<std::string> JSCollator::LOCALE_MATCHER_OPTION_NAME = {"lookup", "best fit"};
const std::vector<CaseFirstOption> JSCollator::CASE_FIRST_OPTION = {
CaseFirstOption::UPPER, CaseFirstOption::LOWER, CaseFirstOption::FALSE_OPTION
};
const std::vector<std::string> JSCollator::CASE_FIRST_OPTION_NAME = {"upper", "lower", "false"};
const std::set<std::string> JSCollator::RELEVANT_EXTENSION_KEYS = {"co", "kn", "kf"};
const std::vector<SensitivityOption> JSCollator::SENSITIVITY_OPTION = {
SensitivityOption::BASE, SensitivityOption::ACCENT,
SensitivityOption::CASE, SensitivityOption::VARIANT
};
const std::vector<std::string> JSCollator::SENSITIVITY_OPTION_NAME = {"base", "accent", "case", "variant"};
const std::vector<UsageOption> JSCollator::USAGE_OPTION = {UsageOption::SORT, UsageOption::SEARCH};
const std::vector<std::string> JSCollator::USAGE_OPTION_NAME = {"sort", "search"};
// All the available locales that are statically known to fulfill fast path conditions.
const char* const JSCollator::FAST_LOCALE[] = {
"en-US", "en", "fr", "es", "de", "pt", "it", "ca",
"de-AT", "fi", "id", "id-ID", "ms", "nl", "pl", "ro",
"sl", "sv", "sw", "vi", "en-DE", "en-GB",
};
JSHandle<TaggedArray> JSCollator::GetAvailableLocales(JSThread *thread, bool enableLocaleCache)
{
@ -99,7 +127,7 @@ JSHandle<JSCollator> JSCollator::InitializeCollator(JSThread *thread,
}
// 4. Let usage be ? GetOption(options, "usage", "string", « "sort", "search" », "sort").
auto usage = JSLocale::GetOptionOfString<UsageOption>(thread, optionsObject, globalConst->GetHandledUsageString(),
{UsageOption::SORT, UsageOption::SEARCH}, {"sort", "search"},
JSCollator::USAGE_OPTION, JSCollator::USAGE_OPTION_NAME,
UsageOption::SORT);
RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSCollator, thread);
collator->SetUsage(usage);
@ -107,7 +135,7 @@ JSHandle<JSCollator> JSCollator::InitializeCollator(JSThread *thread,
// 5. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit").
auto matcher = JSLocale::GetOptionOfString<LocaleMatcherOption>(
thread, optionsObject, globalConst->GetHandledLocaleMatcherString(),
{LocaleMatcherOption::LOOKUP, LocaleMatcherOption::BEST_FIT}, {"lookup", "best fit"},
JSCollator::LOCALE_MATCHER_OPTION, JSCollator::LOCALE_MATCHER_OPTION_NAME,
LocaleMatcherOption::BEST_FIT);
RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSCollator, thread);
@ -138,13 +166,12 @@ JSHandle<JSCollator> JSCollator::InitializeCollator(JSThread *thread,
// 14. Let caseFirst be ? GetOption(options, "caseFirst", "string", « "upper", "lower", "false" », undefined).
CaseFirstOption caseFirst = JSLocale::GetOptionOfString<CaseFirstOption>(
thread, optionsObject, globalConst->GetHandledCaseFirstString(),
{CaseFirstOption::UPPER, CaseFirstOption::LOWER, CaseFirstOption::FALSE_OPTION}, {"upper", "lower", "false"},
JSCollator::CASE_FIRST_OPTION, JSCollator::CASE_FIRST_OPTION_NAME,
CaseFirstOption::UNDEFINED);
RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSCollator, thread);
collator->SetCaseFirst(caseFirst);
// 16. Let relevantExtensionKeys be %Collator%.[[RelevantExtensionKeys]].
std::set<std::string> relevantExtensionKeys = {"co", "kn", "kf"};
// 17. Let r be ResolveLocale(%Collator%.[[AvailableLocales]], requestedLocales, opt,
// %Collator%.[[RelevantExtensionKeys]], localeData).
@ -155,7 +182,7 @@ JSHandle<JSCollator> JSCollator::InitializeCollator(JSThread *thread,
availableLocales = GetAvailableLocales(thread, enableLocaleCache);
}
ResolvedLocale r =
JSLocale::ResolveLocale(thread, availableLocales, requestedLocales, matcher, relevantExtensionKeys);
JSLocale::ResolveLocale(thread, availableLocales, requestedLocales, matcher, RELEVANT_EXTENSION_KEYS);
RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSCollator, thread);
icu::Locale icuLocale = r.localeData;
JSHandle<EcmaString> localeStr = intl::LocaleHelper::ToLanguageTag(thread, icuLocale);
@ -251,8 +278,8 @@ JSHandle<JSCollator> JSCollator::InitializeCollator(JSThread *thread,
// undefined).
SensitivityOption sensitivity = JSLocale::GetOptionOfString<SensitivityOption>(
thread, optionsObject, globalConst->GetHandledSensitivityString(),
{SensitivityOption::BASE, SensitivityOption::ACCENT, SensitivityOption::CASE, SensitivityOption::VARIANT},
{"base", "accent", "case", "variant"}, SensitivityOption::UNDEFINED);
JSCollator::SENSITIVITY_OPTION, JSCollator::SENSITIVITY_OPTION_NAME,
SensitivityOption::UNDEFINED);
RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSCollator, thread);
// 25. If sensitivity is undefined, then
// a. If usage is "sort", then
@ -474,12 +501,6 @@ JSHandle<JSObject> JSCollator::ResolvedOptions(JSThread *thread, const JSHandle<
CompareStringsOption JSCollator::CompareStringsOptionFor(JSThread* thread,
JSHandle<JSTaggedValue> locales)
{
// All the available locales that are statically known to fulfill fast path conditions.
static const char* const FAST_LOCALE[] = {
"en-US", "en", "fr", "es", "de", "pt", "it", "ca",
"de-AT", "fi", "id", "id-ID", "ms", "nl", "pl", "ro",
"sl", "sv", "sw", "vi", "en-DE", "en-GB",
};
if (locales->IsUndefined()) {
auto context = thread->GetCurrentEcmaContext();
auto defaultCompareOption = context->GetDefaultCompareStringsOption();

View File

@ -35,6 +35,23 @@ public:
static const std::map<CaseFirstOption, UColAttributeValue> uColAttributeValueMap;
static const std::vector<LocaleMatcherOption> LOCALE_MATCHER_OPTION;
static const std::vector<std::string> LOCALE_MATCHER_OPTION_NAME;
static const std::vector<CaseFirstOption> CASE_FIRST_OPTION;
static const std::vector<std::string> CASE_FIRST_OPTION_NAME;
static const std::set<std::string> RELEVANT_EXTENSION_KEYS;
static const std::vector<SensitivityOption> SENSITIVITY_OPTION;
static const std::vector<std::string> SENSITIVITY_OPTION_NAME;
static const std::vector<UsageOption> USAGE_OPTION;
static const std::vector<std::string> USAGE_OPTION_NAME;
// All the available locales that are statically known to fulfill fast path conditions.
static const char *const FAST_LOCALE[];
CAST_CHECK(JSCollator, IsJSCollator);
static constexpr size_t ICU_FIELD_OFFSET = JSObject::SIZE;

View File

@ -35,6 +35,41 @@
#endif
namespace panda::ecmascript {
const std::vector<LocaleMatcherOption> JSDisplayNames::LOCALE_MATCHER_OPTION = {
LocaleMatcherOption::LOOKUP, LocaleMatcherOption::BEST_FIT
};
const std::vector<std::string> JSDisplayNames::LOCALE_MATCHER_OPTION_NAME = {"lookup", "best fit"};
const std::vector<StyOption> JSDisplayNames::STY_OPTION = {
StyOption::NARROW, StyOption::SHORT, StyOption::LONG
};
const std::vector<std::string> JSDisplayNames::STY_OPTION_NAME = {"narrow", "short", "long"};
const std::vector<TypednsOption> JSDisplayNames::TYPED_NS_OPTION = {
TypednsOption::LANGUAGE, TypednsOption::REGION,
TypednsOption::SCRIPT, TypednsOption::CURRENCY,
TypednsOption::CALENDAR, TypednsOption::DATETIMEFIELD
};
const std::vector<std::string> JSDisplayNames::TYPED_NS_OPTION_NAME = {
"language", "region", "script", "currency",
"calendar", "dateTimeField"
};
const std::vector<FallbackOption> JSDisplayNames::FALLBACK_OPTION = {
FallbackOption::CODE, FallbackOption::NONE
};
const std::vector<std::string> JSDisplayNames::FALLBACK_OPTION_OPTION_NAME = {
"code", "none"
};
const std::vector<LanguageDisplayOption> JSDisplayNames::LANGUAGE_DISPLAY_OPTION = {
LanguageDisplayOption::DIALECT, LanguageDisplayOption::STANDARD
};
const std::vector<std::string> JSDisplayNames::LANGUAGE_DISPLAY_OPTION_NAME = {
"dialect", "standard"
};
icu::LocaleDisplayNames *JSDisplayNames::GetIcuLocaleDisplayNames() const
{
ASSERT(GetIcuLDN().IsJSNativePointer());
@ -125,8 +160,9 @@ JSHandle<JSDisplayNames> JSDisplayNames::InitializeDisplayNames(JSThread *thread
// 8. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit").
JSHandle<JSTaggedValue> property = globalConst->GetHandledLocaleMatcherString();
auto matcher = JSLocale::GetOptionOfString<LocaleMatcherOption>(
thread, optionsObject, property, {LocaleMatcherOption::LOOKUP, LocaleMatcherOption::BEST_FIT},
{"lookup", "best fit"}, LocaleMatcherOption::BEST_FIT);
thread, optionsObject, property,
JSDisplayNames::LOCALE_MATCHER_OPTION, JSDisplayNames::LOCALE_MATCHER_OPTION_NAME,
LocaleMatcherOption::BEST_FIT);
RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSDisplayNames, thread);
// 10. Let r be ResolveLocale(%DisplayNames%.[[AvailableLocales]], requestedLocales, opt,
@ -146,8 +182,8 @@ JSHandle<JSDisplayNames> JSDisplayNames::InitializeDisplayNames(JSThread *thread
// 11. Let style be ? GetOption(options, "style", "string", « "narrow", "short", "long" », "long").
property = globalConst->GetHandledStyleString();
auto StyOpt = JSLocale::GetOptionOfString<StyOption>(thread, optionsObject, property,
{StyOption::NARROW, StyOption::SHORT, StyOption::LONG},
{"narrow", "short", "long"}, StyOption::LONG);
JSDisplayNames::STY_OPTION, JSDisplayNames::STY_OPTION_NAME,
StyOption::LONG);
RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSDisplayNames, thread);
// 12. Set DisplayNames.[[Style]] to style.
@ -157,11 +193,7 @@ JSHandle<JSDisplayNames> JSDisplayNames::InitializeDisplayNames(JSThread *thread
// "undefined").
property = globalConst->GetHandledTypeString();
auto type = JSLocale::GetOptionOfString<TypednsOption>(thread, optionsObject, property,
{TypednsOption::LANGUAGE, TypednsOption::REGION,
TypednsOption::SCRIPT, TypednsOption::CURRENCY,
TypednsOption::CALENDAR, TypednsOption::DATETIMEFIELD},
{"language", "region", "script", "currency",
"calendar", "dateTimeField"},
JSDisplayNames::TYPED_NS_OPTION, JSDisplayNames::TYPED_NS_OPTION_NAME,
TypednsOption::UNDEFINED);
RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSDisplayNames, thread);
@ -176,8 +208,8 @@ JSHandle<JSDisplayNames> JSDisplayNames::InitializeDisplayNames(JSThread *thread
// 16. Let fallback be ? GetOption(options, "fallback", "string", « "code", "none" », "code").
property = globalConst->GetHandledFallbackString();
auto fallback = JSLocale::GetOptionOfString<FallbackOption>(thread, optionsObject, property,
{FallbackOption::CODE, FallbackOption::NONE},
{"code", "none"}, FallbackOption::CODE);
JSDisplayNames::FALLBACK_OPTION, JSDisplayNames::FALLBACK_OPTION_OPTION_NAME,
FallbackOption::CODE);
RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSDisplayNames, thread);
// 17. Set displayNames.[[Fallback]] to fallback.
@ -186,8 +218,9 @@ JSHandle<JSDisplayNames> JSDisplayNames::InitializeDisplayNames(JSThread *thread
// Let languageDisplay be ? GetOption(options, "languageDisplay", string, « "dialect", "standard" », "dialect").
property = globalConst->GetHandledLanguageDisplayString();
auto langDisplay = JSLocale::GetOptionOfString<LanguageDisplayOption>(
thread, optionsObject, property, {LanguageDisplayOption::DIALECT, LanguageDisplayOption::STANDARD},
{"dialect", "standard"}, LanguageDisplayOption::DIALECT);
thread, optionsObject, property,
JSDisplayNames::LANGUAGE_DISPLAY_OPTION,
JSDisplayNames::LANGUAGE_DISPLAY_OPTION_NAME, LanguageDisplayOption::DIALECT);
RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSDisplayNames, thread);
displayNames->SetLanguageDisplay(langDisplay);

View File

@ -63,6 +63,20 @@ enum class LanguageDisplayOption : uint8_t {
class JSDisplayNames : public JSObject {
public:
static const std::vector<LocaleMatcherOption> LOCALE_MATCHER_OPTION;
static const std::vector<std::string> LOCALE_MATCHER_OPTION_NAME;
static const std::vector<StyOption> STY_OPTION;
static const std::vector<std::string> STY_OPTION_NAME;
static const std::vector<TypednsOption> TYPED_NS_OPTION;
static const std::vector<std::string> TYPED_NS_OPTION_NAME;
static const std::vector<FallbackOption> FALLBACK_OPTION;
static const std::vector<std::string> FALLBACK_OPTION_OPTION_NAME;
static const std::vector<LanguageDisplayOption> LANGUAGE_DISPLAY_OPTION;
static const std::vector<std::string> LANGUAGE_DISPLAY_OPTION_NAME;
CAST_CHECK(JSDisplayNames, IsJSDisplayNames);
static constexpr size_t LOCALE_OFFSET = JSObject::SIZE;

View File

@ -34,7 +34,27 @@
#endif
namespace panda::ecmascript {
const std::string LATN_STRING = "latn";
const std::string JSLocale::LATN_STRING = "latn";
const std::vector<LocaleMatcherOption> JSLocale::LOCALE_MATCHER_OPTION = {
LocaleMatcherOption::LOOKUP, LocaleMatcherOption::BEST_FIT
};
const std::vector<std::string> JSLocale::LOCALE_MATCHER_OPTION_NAME = {
"lookup", "best fit"
};
const std::map<std::string, std::set<std::string>> JSLocale::LOCALE_MAP = {
{"hc", {"h11", "h12", "h23", "h24"}},
{"lb", {"strict", "normal", "loose"}},
{"kn", {"true", "false"}},
{"kf", {"upper", "lower", "false"}}
};
const std::vector<std::string> JSLocale::HOUR_CYCLE = {"h11", "h12", "h23", "h24"};
const std::vector<std::string> JSLocale::CASE_FIRST = {"upper", "lower", "false"};
const std::set<std::string> JSLocale::WELL_NUMBER_SYSTEM = {"native", "traditio", "finance"};
const std::set<std::string> JSLocale::WELL_COLLATION = {"standard", "search"};
// 6.4.1 IsValidTimeZoneName ( timeZone )
bool JSLocale::IsValidTimeZoneName(const icu::TimeZone &tz)
{
@ -236,7 +256,7 @@ JSHandle<JSArray> JSLocale::SupportedLocales(JSThread *thread, const JSHandle<Ta
[[maybe_unused]] LocaleMatcherOption matcher = GetOptionOfString<LocaleMatcherOption>(thread,
obj, globalConst->GetHandledLocaleMatcherString(),
{LocaleMatcherOption::LOOKUP, LocaleMatcherOption::BEST_FIT}, {"lookup", "best fit"},
JSLocale::LOCALE_MATCHER_OPTION, JSLocale::LOCALE_MATCHER_OPTION_NAME,
LocaleMatcherOption::BEST_FIT);
RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSArray, thread);
}
@ -445,13 +465,6 @@ ResolvedLocale JSLocale::ResolveLocale(JSThread *thread, const JSHandle<TaggedAr
[[maybe_unused]] LocaleMatcherOption matcher,
const std::set<std::string> &relevantExtensionKeys)
{
std::map<std::string, std::set<std::string>> localeMap = {
{"hc", {"h11", "h12", "h23", "h24"}},
{"lb", {"strict", "normal", "loose"}},
{"kn", {"true", "false"}},
{"kf", {"upper", "lower", "false"}}
};
// 1. Let matcher be options.[[localeMatcher]].
// 2. If matcher is "lookup" "lookup", then
// a. Let r be LookupMatcher(availableLocales, requestedLocales).
@ -497,9 +510,12 @@ ResolvedLocale JSLocale::ResolveLocale(JSThread *thread, const JSHandle<TaggedAr
// c. Let keyLocaleData be foundLocaleData.[[<key>]].
// e. Let value be keyLocaleData[0].
if ((key != "ca") && (key != "co") && (key != "nu")) {
keyLocaleData = localeMap[key];
auto find = JSLocale::LOCALE_MAP.find(key);
if (find != JSLocale::LOCALE_MAP.end()) {
keyLocaleData = find->second;
}
if (key == "") {
keyLocaleData = localeMap["lb"];
keyLocaleData = JSLocale::LOCALE_MAP.at("lb");
}
value = *keyLocaleData.begin();
}
@ -627,7 +643,7 @@ std::string JSLocale::GetNumberingSystem(const icu::Locale &icuLocale)
if (U_SUCCESS(status) != 0) {
return numberingSystem->getName();
}
return LATN_STRING;
return JSLocale::LATN_STRING;
}
bool JSLocale::IsWellFormedCurrencyCode(const std::string &currency)
@ -857,8 +873,6 @@ bool BuildOptionsTags(const JSHandle<EcmaString> &tag, icu::LocaleBuilder *build
bool InsertOptions(JSThread *thread, const JSHandle<JSObject> &options, icu::LocaleBuilder *builder)
{
const std::vector<std::string> hourCycleValues = {"h11", "h12", "h23", "h24"};
const std::vector<std::string> caseFirstValues = {"upper", "lower", "false"};
const std::vector<std::string> emptyValues = {};
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
std::string strResult;
@ -885,7 +899,7 @@ bool InsertOptions(JSThread *thread, const JSHandle<JSObject> &options, icu::Loc
}
bool findhc = JSLocale::GetOptionOfString(thread, options, globalConst->GetHandledHourCycleString(),
hourCycleValues, &strResult);
JSLocale::HOUR_CYCLE, &strResult);
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
if (findhc) {
if (!uloc_toLegacyType(uloc_toLegacyKey("hc"), strResult.c_str())) {
@ -896,7 +910,7 @@ bool InsertOptions(JSThread *thread, const JSHandle<JSObject> &options, icu::Loc
}
bool findkf = JSLocale::GetOptionOfString(thread, options, globalConst->GetHandledCaseFirstString(),
caseFirstValues, &strResult);
JSLocale::CASE_FIRST, &strResult);
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
if (findkf) {
if (!uloc_toLegacyType(uloc_toLegacyKey("kf"), strResult.c_str())) {

View File

@ -49,6 +49,7 @@
#include "unicode/uversion.h"
namespace panda::ecmascript {
enum class OptionType : uint8_t { STRING = 0x01, BOOLEAN };
enum class LocaleMatcherOption : uint8_t { LOOKUP = 0x01, BEST_FIT, EXCEPTION };
enum class FormatMatcherOption : uint8_t { BASIC = 0x01, BEST_FIT, EXCEPTION };
@ -148,6 +149,18 @@ struct TagElements {
class JSLocale : public JSObject {
public:
static const std::set<std::string> WELL_NUMBER_SYSTEM;
static const std::set<std::string> WELL_COLLATION;
static const std::string LATN_STRING;
static const std::vector<LocaleMatcherOption> LOCALE_MATCHER_OPTION;
static const std::vector<std::string> LOCALE_MATCHER_OPTION_NAME;
static const std::map<std::string, std::set<std::string>> LOCALE_MAP;
static const std::vector<std::string> HOUR_CYCLE;
static const std::vector<std::string> CASE_FIRST;
static JSLocale *Cast(TaggedObject *object)
{
ASSERT(JSTaggedValue(object).IsJSLocale());
@ -321,8 +334,7 @@ public:
static bool IsWellNumberingSystem(const std::string &value)
{
std::set<std::string> irregularList = {"native", "traditio", "finance"};
if (irregularList.find(value) != irregularList.end()) {
if (JSLocale::WELL_NUMBER_SYSTEM.find(value) != JSLocale::WELL_NUMBER_SYSTEM.end()) {
return false;
}
UErrorCode status = U_ZERO_ERROR;
@ -335,8 +347,7 @@ public:
static bool IsWellCollation(const icu::Locale &locale, const std::string &value)
{
std::set<std::string> irregularList = {"standard", "search"};
if (irregularList.find(value) != irregularList.end()) {
if (JSLocale::WELL_COLLATION.find(value) != JSLocale::WELL_COLLATION.end()) {
return false;
}
return IsWellExtension<icu::Collator>(locale, "collation", value);

View File

@ -19,8 +19,57 @@
#include "ecmascript/object_factory-inl.h"
namespace panda::ecmascript {
constexpr uint32_t DEFAULT_FRACTION_DIGITS = 2;
constexpr uint32_t PERUNIT_STRING = 5;
const std::vector<StyleOption> JSNumberFormat::STYLE_OPTION = {
StyleOption::DECIMAL, StyleOption::PERCENT, StyleOption::CURRENCY, StyleOption::UNIT
};
const std::vector<std::string> JSNumberFormat::STYLE_OPTION_NAME = {
"decimal", "percent", "currency", "unit"
};
const std::vector<CurrencyDisplayOption> JSNumberFormat::CURRENCY_DISPLAY_OPTION = {
CurrencyDisplayOption::CODE, CurrencyDisplayOption::SYMBOL,
CurrencyDisplayOption::NARROWSYMBOL, CurrencyDisplayOption::NAME
};
const std::vector<std::string> JSNumberFormat::CURRENCY_DISPLAY_OPTION_NAME = {
"code", "symbol", "narrowSymbol", "name"
};
const std::vector<CurrencySignOption> JSNumberFormat::CURRENCY_SIGN_OPTION = {
CurrencySignOption::STANDARD, CurrencySignOption::ACCOUNTING
};
const std::vector<std::string> JSNumberFormat::CURRENCY_SIGN_OPTION_NAME = {"standard", "accounting"};
const std::vector<UnitDisplayOption> JSNumberFormat::UNIT_DISPLAY_OPTION = {
UnitDisplayOption::SHORT, UnitDisplayOption::NARROW, UnitDisplayOption::LONG
};
const std::vector<std::string> JSNumberFormat::UNIT_DISPLAY_OPTION_NAME = {"short", "narrow", "long"};
const std::vector<LocaleMatcherOption> JSNumberFormat::LOCALE_MATCHER_OPTION = {
LocaleMatcherOption::LOOKUP, LocaleMatcherOption::BEST_FIT
};
const std::vector<std::string> JSNumberFormat::LOCALE_MATCHER_OPTION_NAME = {"lookup", "best fit"};
const std::vector<NotationOption> JSNumberFormat::NOTATION_OPTION = {
NotationOption::STANDARD, NotationOption::SCIENTIFIC,
NotationOption::ENGINEERING, NotationOption::COMPACT
};
const std::vector<std::string> JSNumberFormat::NOTATION_OPTION_NAME = {
"standard", "scientific", "engineering", "compact"
};
const std::vector<SignDisplayOption> JSNumberFormat::SIGN_DISPLAY_OPTION = {
SignDisplayOption::AUTO, SignDisplayOption::NEVER,
SignDisplayOption::ALWAYS, SignDisplayOption::EXCEPTZERO
};
const std::vector<std::string> JSNumberFormat::SIGN_DISPLAY_OPTION_NAME = {
"auto", "never", "always", "exceptZero"
};
const std::vector<CompactDisplayOption> JSNumberFormat::COMPACT_DISPLAY_OPTION = {
CompactDisplayOption::SHORT, CompactDisplayOption::LONG
};
const std::vector<std::string> JSNumberFormat::COMPACT_DISPLAY_OPTION_NAME = {"short", "long"};
JSHandle<JSTaggedValue> OptionToEcmaString(JSThread *thread, StyleOption style)
{
@ -225,7 +274,7 @@ bool IsWellFormedUnitIdentifier(const std::string &unit, icu::MeasureUnit &icuUn
// 2. If the substring "-per-" does not occur exactly once in unitIdentifier,
// a. then false
size_t afterPos = pos + PERUNIT_STRING;
size_t afterPos = pos + JSNumberFormat::PERUNIT_STRING;
if (pos == std::string::npos || unit.find("-per-", afterPos) != std::string::npos) {
return false;
}
@ -241,7 +290,7 @@ bool IsWellFormedUnitIdentifier(const std::string &unit, icu::MeasureUnit &icuUn
}
// 5. Let denominator be the substring of unitIdentifier from just after "-per-" to the end.
std::string denominator = unit.substr(pos + PERUNIT_STRING);
std::string denominator = unit.substr(pos + JSNumberFormat::PERUNIT_STRING);
// 6. If the result of IsSanctionedUnitIdentifier(denominator) is false, then
// a. Return false
@ -270,8 +319,8 @@ FractionDigitsOption SetNumberFormatUnitOptions(JSThread *thread,
JSHandle<JSTaggedValue> property = globalConst->GetHandledStyleString();
auto style = JSLocale::GetOptionOfString<StyleOption>(
thread, optionsObject, property,
{StyleOption::DECIMAL, StyleOption::PERCENT, StyleOption::CURRENCY, StyleOption::UNIT},
{"decimal", "percent", "currency", "unit"}, StyleOption::DECIMAL);
JSNumberFormat::STYLE_OPTION, JSNumberFormat::STYLE_OPTION_NAME,
StyleOption::DECIMAL);
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, fractionDigitsOption);
// 4. Set intlObj.[[Style]] to style.
@ -307,17 +356,17 @@ FractionDigitsOption SetNumberFormatUnitOptions(JSThread *thread,
property = globalConst->GetHandledCurrencyDisplayString();
auto currencyDisplay = JSLocale::GetOptionOfString<CurrencyDisplayOption>(
thread, optionsObject, property,
{CurrencyDisplayOption::CODE, CurrencyDisplayOption::SYMBOL, CurrencyDisplayOption::NARROWSYMBOL,
CurrencyDisplayOption::NAME},
{"code", "symbol", "narrowSymbol", "name"}, CurrencyDisplayOption::SYMBOL);
JSNumberFormat::CURRENCY_DISPLAY_OPTION, JSNumberFormat::CURRENCY_DISPLAY_OPTION_NAME,
CurrencyDisplayOption::SYMBOL);
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, fractionDigitsOption);
numberFormat->SetCurrencyDisplay(currencyDisplay);
// 9. Let currencySign be ? GetOption(options, "currencySign", "string", « "standard", "accounting" », "standard").
property = globalConst->GetHandledCurrencySignString();
auto currencySign = JSLocale::GetOptionOfString<CurrencySignOption>(
thread, optionsObject, property, {CurrencySignOption::STANDARD, CurrencySignOption::ACCOUNTING},
{"standard", "accounting"}, CurrencySignOption::STANDARD);
thread, optionsObject, property,
JSNumberFormat::CURRENCY_SIGN_OPTION, JSNumberFormat::CURRENCY_SIGN_OPTION_NAME,
CurrencySignOption::STANDARD);
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, fractionDigitsOption);
numberFormat->SetCurrencySign(currencySign);
@ -351,8 +400,9 @@ FractionDigitsOption SetNumberFormatUnitOptions(JSThread *thread,
// 13. Let unitDisplay be ? GetOption(options, "unitDisplay", "string", « "short", "narrow", "long" », "short").
property = globalConst->GetHandledUnitDisplayString();
auto unitDisplay = JSLocale::GetOptionOfString<UnitDisplayOption>(
thread, optionsObject, property, {UnitDisplayOption::SHORT, UnitDisplayOption::NARROW, UnitDisplayOption::LONG},
{"short", "narrow", "long"}, UnitDisplayOption::SHORT);
thread, optionsObject, property,
JSNumberFormat::UNIT_DISPLAY_OPTION, JSNumberFormat::UNIT_DISPLAY_OPTION_NAME,
UnitDisplayOption::SHORT);
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, fractionDigitsOption);
numberFormat->SetUnitDisplay(unitDisplay);
@ -463,8 +513,9 @@ void JSNumberFormat::InitializeNumberFormat(JSThread *thread, const JSHandle<JSN
// 5. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit").
JSHandle<JSTaggedValue> property = globalConst->GetHandledLocaleMatcherString();
auto matcher = JSLocale::GetOptionOfString<LocaleMatcherOption>(
thread, optionsObject, property, {LocaleMatcherOption::LOOKUP, LocaleMatcherOption::BEST_FIT},
{"lookup", "best fit"}, LocaleMatcherOption::BEST_FIT);
thread, optionsObject, property,
JSNumberFormat::LOCALE_MATCHER_OPTION, JSNumberFormat::LOCALE_MATCHER_OPTION_NAME,
LocaleMatcherOption::BEST_FIT);
RETURN_IF_ABRUPT_COMPLETION(thread);
// 7. Let numberingSystem be ? GetOption(options, "numberingSystem", "string", undefined, undefined).
@ -569,8 +620,8 @@ void JSNumberFormat::InitializeNumberFormat(JSThread *thread, const JSHandle<JSN
property = globalConst->GetHandledNotationString();
auto notation = JSLocale::GetOptionOfString<NotationOption>(
thread, optionsObject, property,
{NotationOption::STANDARD, NotationOption::SCIENTIFIC, NotationOption::ENGINEERING, NotationOption::COMPACT},
{"standard", "scientific", "engineering", "compact"}, NotationOption::STANDARD);
JSNumberFormat::NOTATION_OPTION, JSNumberFormat::NOTATION_OPTION_NAME,
NotationOption::STANDARD);
RETURN_IF_ABRUPT_COMPLETION(thread);
numberFormat->SetNotation(notation);
@ -583,7 +634,8 @@ void JSNumberFormat::InitializeNumberFormat(JSThread *thread, const JSHandle<JSN
// 22. Let compactDisplay be ? GetOptionOfString(options, "compactDisplay", "string", « "short", "long" », "short").
property = globalConst->GetHandledCompactDisplayString();
auto compactDisplay = JSLocale::GetOptionOfString<CompactDisplayOption>(
thread, optionsObject, property, {CompactDisplayOption::SHORT, CompactDisplayOption::LONG}, {"short", "long"},
thread, optionsObject, property,
JSNumberFormat::COMPACT_DISPLAY_OPTION, JSNumberFormat::COMPACT_DISPLAY_OPTION_NAME,
CompactDisplayOption::SHORT);
numberFormat->SetCompactDisplay(compactDisplay);
@ -632,8 +684,8 @@ void JSNumberFormat::InitializeNumberFormat(JSThread *thread, const JSHandle<JSN
property = globalConst->GetHandledSignDisplayString();
auto signDisplay = JSLocale::GetOptionOfString<SignDisplayOption>(
thread, optionsObject, property,
{SignDisplayOption::AUTO, SignDisplayOption::NEVER, SignDisplayOption::ALWAYS, SignDisplayOption::EXCEPTZERO},
{"auto", "never", "always", "exceptZero"}, SignDisplayOption::AUTO);
JSNumberFormat::SIGN_DISPLAY_OPTION, JSNumberFormat::SIGN_DISPLAY_OPTION_NAME,
SignDisplayOption::AUTO);
RETURN_IF_ABRUPT_COMPLETION(thread);
numberFormat->SetSignDisplay(signDisplay);
@ -701,7 +753,7 @@ int32_t JSNumberFormat::CurrencyDigits(const icu::UnicodeString &currency)
if (U_SUCCESS(status)) {
return fractionDigits;
}
return DEFAULT_FRACTION_DIGITS;
return JSNumberFormat::DEFAULT_FRACTION_DIGITS;
}
icu::number::LocalizedNumberFormatter *JSNumberFormat::GetCachedIcuNumberFormatter(JSThread *thread,

View File

@ -52,6 +52,31 @@ static const std::set<std::string> SANCTIONED_UNIT({ "acre", "bit", "byte", "cel
class JSNumberFormat : public JSObject {
public:
static constexpr uint32_t DEFAULT_FRACTION_DIGITS = 2;
static constexpr uint32_t PERUNIT_STRING = 5;
static const std::vector<StyleOption> STYLE_OPTION;
static const std::vector<std::string> STYLE_OPTION_NAME;
static const std::vector<CurrencyDisplayOption> CURRENCY_DISPLAY_OPTION;
static const std::vector<std::string> CURRENCY_DISPLAY_OPTION_NAME;
static const std::vector<CurrencySignOption> CURRENCY_SIGN_OPTION;
static const std::vector<std::string> CURRENCY_SIGN_OPTION_NAME;
static const std::vector<UnitDisplayOption> UNIT_DISPLAY_OPTION;
static const std::vector<std::string> UNIT_DISPLAY_OPTION_NAME;
static const std::vector<LocaleMatcherOption> LOCALE_MATCHER_OPTION;
static const std::vector<std::string> LOCALE_MATCHER_OPTION_NAME;
static const std::vector<NotationOption> NOTATION_OPTION;
static const std::vector<std::string> NOTATION_OPTION_NAME;
static const std::vector<SignDisplayOption> SIGN_DISPLAY_OPTION;
static const std::vector<std::string> SIGN_DISPLAY_OPTION_NAME;
static const std::vector<CompactDisplayOption> COMPACT_DISPLAY_OPTION;
static const std::vector<std::string> COMPACT_DISPLAY_OPTION_NAME;
CAST_CHECK(JSNumberFormat, IsJSNumberFormat);
static constexpr size_t LOCALE_OFFSET = JSObject::SIZE;