mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 08:03:29 +00:00
Extract ICU locale relevant processing from JSLocale
Issue:Extract ICU locale relevant processing from JSLocale Signed-off-by: Zhenyu Pan <panzhenyu1@huawei.com> Change-Id: I796890fa7999d8ec9c40646fc3fe899bc439f12f
This commit is contained in:
parent
c91ddc64a9
commit
24b217ca04
1
BUILD.gn
1
BUILD.gn
@ -400,6 +400,7 @@ ecma_source = [
|
||||
"ecmascript/base/json_parser.cpp",
|
||||
"ecmascript/base/json_stringifier.cpp",
|
||||
"ecmascript/base/number_helper.cpp",
|
||||
"ecmascript/base/locale_helper.cpp",
|
||||
"ecmascript/base/string_helper.cpp",
|
||||
"ecmascript/base/typed_array_helper.cpp",
|
||||
"ecmascript/base/utf_helper.cpp",
|
||||
|
466
ecmascript/base/locale_helper.cpp
Normal file
466
ecmascript/base/locale_helper.cpp
Normal file
@ -0,0 +1,466 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecmascript/base/locale_helper.h"
|
||||
|
||||
#include "ecmascript/base/string_helper.h"
|
||||
#include "ecmascript/ecma_macros.h"
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/object_factory.h"
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wshadow"
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wshadow"
|
||||
#endif
|
||||
#include "unicode/localebuilder.h"
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
namespace panda::ecmascript::base {
|
||||
JSHandle<EcmaString> LocaleHelper::UStringToString(JSThread *thread, const icu::UnicodeString &string)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
return factory->NewFromUtf16(reinterpret_cast<const uint16_t *>(string.getBuffer()), string.length());
|
||||
}
|
||||
|
||||
JSHandle<EcmaString> LocaleHelper::UStringToString(JSThread *thread, const icu::UnicodeString &string, int32_t begin,
|
||||
int32_t end)
|
||||
{
|
||||
return UStringToString(thread, string.tempSubStringBetween(begin, end));
|
||||
}
|
||||
|
||||
// 9.2.1 CanonicalizeLocaleList ( locales )
|
||||
JSHandle<TaggedArray> LocaleHelper::CanonicalizeLocaleList(JSThread *thread, const JSHandle<JSTaggedValue> &locales)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
// 1. If locales is undefined, then
|
||||
// a. Return a new empty List.
|
||||
if (locales->IsUndefined()) {
|
||||
return factory->EmptyArray();
|
||||
}
|
||||
// 2. Let seen be a new empty List.
|
||||
JSHandle<TaggedArray> localeSeen = factory->NewTaggedArray(1);
|
||||
// 3. If Type(locales) is String or Type(locales) is Object and locales has an [[InitializedLocale]] internal slot,
|
||||
// then
|
||||
// a. Let O be CreateArrayFromList(« locales »).
|
||||
// 4. Else,
|
||||
// a.Let O be ? ToObject(locales).
|
||||
if (locales->IsString()) {
|
||||
JSHandle<EcmaString> tag = JSHandle<EcmaString>::Cast(locales);
|
||||
JSHandle<TaggedArray> temp = factory->NewTaggedArray(1);
|
||||
temp->Set(thread, 0, tag.GetTaggedValue());
|
||||
JSHandle<JSArray> obj = JSArray::CreateArrayFromList(thread, temp);
|
||||
JSHandle<TaggedArray> finalSeen = CanonicalizeHelper<JSArray>(thread, obj, localeSeen);
|
||||
return finalSeen;
|
||||
} else if (locales->IsJSLocale()) {
|
||||
JSHandle<EcmaString> tag = JSLocale::ToString(thread, JSHandle<JSLocale>::Cast(locales));
|
||||
JSHandle<TaggedArray> temp = factory->NewTaggedArray(1);
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
|
||||
temp->Set(thread, 0, tag.GetTaggedValue());
|
||||
JSHandle<JSArray> obj = JSArray::CreateArrayFromList(thread, temp);
|
||||
JSHandle<TaggedArray> finalSeen = CanonicalizeHelper<JSArray>(thread, obj, localeSeen);
|
||||
return finalSeen;
|
||||
} else {
|
||||
JSHandle<JSObject> obj = JSTaggedValue::ToObject(thread, locales);
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
|
||||
JSHandle<TaggedArray> finalSeen = CanonicalizeHelper<JSObject>(thread, obj, localeSeen);
|
||||
return finalSeen;
|
||||
}
|
||||
return localeSeen;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
JSHandle<TaggedArray> LocaleHelper::CanonicalizeHelper(JSThread *thread, JSHandle<T> &obj, JSHandle<TaggedArray> &seen)
|
||||
{
|
||||
OperationResult operationResult = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(obj),
|
||||
thread->GlobalConstants()->GetHandledLengthString());
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
|
||||
JSTaggedNumber len = JSTaggedValue::ToLength(thread, operationResult.GetValue());
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
// 2. Let seen be a new empty List.
|
||||
uint32_t requestedLocalesLen = len.ToUint32();
|
||||
seen = factory->NewTaggedArray(requestedLocalesLen);
|
||||
// 6. Let k be 0.
|
||||
// 7. Repeat, while k < len
|
||||
JSMutableHandle<JSTaggedValue> pk(thread, JSTaggedValue::Undefined());
|
||||
JSMutableHandle<JSTaggedValue> tag(thread, JSTaggedValue::Undefined());
|
||||
uint32_t index = 0;
|
||||
JSHandle<JSTaggedValue> objTagged = JSHandle<JSTaggedValue>::Cast(obj);
|
||||
for (uint32_t k = 0; k < requestedLocalesLen; k++) {
|
||||
// a. Let Pk be ToString(k).
|
||||
JSHandle<JSTaggedValue> kHandle(thread, JSTaggedValue(k));
|
||||
JSHandle<EcmaString> str = JSTaggedValue::ToString(thread, kHandle);
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
|
||||
pk.Update(str.GetTaggedValue());
|
||||
// b. Let kPresent be ? HasProperty(O, Pk).
|
||||
bool kPresent = JSTaggedValue::HasProperty(thread, objTagged, pk);
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
|
||||
|
||||
// c. If kPresent is true, then
|
||||
if (kPresent) {
|
||||
// i. Let kValue be ? Get(O, Pk).
|
||||
OperationResult result = JSTaggedValue::GetProperty(thread, objTagged, pk);
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
|
||||
JSHandle<JSTaggedValue> kValue = result.GetValue();
|
||||
// ii. If Type(kValue) is not String or Object, throw a TypeError exception.
|
||||
if (!kValue->IsString() && !kValue->IsJSObject()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "kValue is not String or Object.", factory->EmptyArray());
|
||||
}
|
||||
// iii. If Type(kValue) is Object and kValue has an [[InitializedLocale]] internal slot, then
|
||||
// 1. Let tag be kValue.[[Locale]].
|
||||
// iv. Else,
|
||||
// 1. Let tag be ? ToString(kValue).
|
||||
if (kValue->IsJSLocale()) {
|
||||
JSHandle<EcmaString> kValueStr = JSLocale::ToString(thread, JSHandle<JSLocale>::Cast(kValue));
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
|
||||
tag.Update(kValueStr.GetTaggedValue());
|
||||
} else {
|
||||
JSHandle<EcmaString> kValueString = JSTaggedValue::ToString(thread, kValue);
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
|
||||
JSHandle<EcmaString> canonicalStr = CanonicalizeUnicodeLocaleId(thread, kValueString);
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
|
||||
tag.Update(canonicalStr.GetTaggedValue());
|
||||
}
|
||||
// vii. If canonicalizedTag is not an element of seen, append canonicalizedTag as the last element of seen.
|
||||
bool isExist = false;
|
||||
uint32_t seenLen = seen->GetLength();
|
||||
for (uint32_t i = 0; i < seenLen; i++) {
|
||||
if (JSTaggedValue::SameValue(seen->Get(thread, i), tag.GetTaggedValue())) {
|
||||
isExist = true;
|
||||
}
|
||||
}
|
||||
if (!isExist) {
|
||||
seen->Set(thread, index++, JSHandle<JSTaggedValue>::Cast(tag));
|
||||
}
|
||||
}
|
||||
// d. Increase k by 1.
|
||||
}
|
||||
// set capacity
|
||||
seen = TaggedArray::SetCapacity(thread, seen, index);
|
||||
// 8. Return seen.
|
||||
return seen;
|
||||
}
|
||||
|
||||
// 6.2.3 CanonicalizeUnicodeLocaleId( locale )
|
||||
JSHandle<EcmaString> LocaleHelper::CanonicalizeUnicodeLocaleId(JSThread *thread, const JSHandle<EcmaString> &locale)
|
||||
{
|
||||
[[maybe_unused]] ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
if (!IsStructurallyValidLanguageTag(locale)) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "invalid locale", factory->GetEmptyString());
|
||||
}
|
||||
|
||||
if (EcmaStringAccessor(locale).GetLength() == 0 || EcmaStringAccessor(locale).IsUtf16()) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "invalid locale", factory->GetEmptyString());
|
||||
}
|
||||
|
||||
std::string localeCStr = ConvertToStdString(locale);
|
||||
std::transform(localeCStr.begin(), localeCStr.end(), localeCStr.begin(), AsciiAlphaToLower);
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
icu::Locale formalLocale = icu::Locale::forLanguageTag(localeCStr.c_str(), status);
|
||||
if ((U_FAILURE(status) != 0) || (formalLocale.isBogus() != 0)) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "invalid locale", factory->GetEmptyString());
|
||||
}
|
||||
|
||||
// Resets the LocaleBuilder to match the locale.
|
||||
// Returns an instance of Locale created from the fields set on this builder.
|
||||
formalLocale = icu::LocaleBuilder().setLocale(formalLocale).build(status);
|
||||
// Canonicalize the locale ID of this object according to CLDR.
|
||||
formalLocale.canonicalize(status);
|
||||
if ((U_FAILURE(status) != 0) || (formalLocale.isBogus() != 0)) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "invalid locale", factory->GetEmptyString());
|
||||
}
|
||||
JSHandle<EcmaString> languageTag = ToLanguageTag(thread, formalLocale);
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(EcmaString, thread);
|
||||
return languageTag;
|
||||
}
|
||||
|
||||
JSHandle<EcmaString> LocaleHelper::ToLanguageTag(JSThread *thread, const icu::Locale &locale)
|
||||
{
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
auto result = locale.toLanguageTag<std::string>(status);
|
||||
bool flag = (U_FAILURE(status) == 0) ? true : false;
|
||||
if (!flag) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "invalid locale", factory->GetEmptyString());
|
||||
}
|
||||
size_t findBeginning = result.find("-u-");
|
||||
std::string finalRes;
|
||||
std::string tempRes;
|
||||
if (findBeginning == std::string::npos) {
|
||||
return factory->NewFromStdString(result);
|
||||
}
|
||||
size_t specialBeginning = findBeginning + INTL_INDEX_THREE;
|
||||
size_t specialCount = 0;
|
||||
while ((specialBeginning < result.size()) && (result[specialBeginning] != '-')) {
|
||||
specialCount++;
|
||||
specialBeginning++;
|
||||
}
|
||||
if (findBeginning != std::string::npos) {
|
||||
// It begin with "-u-xx" or with more elements.
|
||||
tempRes = result.substr(0, findBeginning + INTL_INDEX_THREE + specialCount);
|
||||
if (result.size() <= findBeginning + INTL_INDEX_THREE + specialCount) {
|
||||
return factory->NewFromStdString(result);
|
||||
}
|
||||
std::string leftStr = result.substr(findBeginning + INTL_INDEX_THREE + specialCount + 1);
|
||||
std::istringstream temp(leftStr);
|
||||
std::string buffer;
|
||||
std::vector<std::string> resContainer;
|
||||
while (getline(temp, buffer, '-')) {
|
||||
if (buffer != "true" && buffer != "yes") {
|
||||
resContainer.push_back(buffer);
|
||||
}
|
||||
}
|
||||
for (auto it = resContainer.begin(); it != resContainer.end(); it++) {
|
||||
std::string tag = "-";
|
||||
tag += *it;
|
||||
finalRes += tag;
|
||||
}
|
||||
}
|
||||
if (!finalRes.empty()) {
|
||||
tempRes += finalRes;
|
||||
}
|
||||
result = tempRes;
|
||||
return factory->NewFromStdString(result);
|
||||
}
|
||||
|
||||
// 6.2.2 IsStructurallyValidLanguageTag( locale )
|
||||
bool LocaleHelper::IsStructurallyValidLanguageTag(const JSHandle<EcmaString> &tag)
|
||||
{
|
||||
std::string tagCollection = ConvertToStdString(tag);
|
||||
std::vector<std::string> containers;
|
||||
std::string substring;
|
||||
std::set<std::string> uniqueSubtags;
|
||||
size_t address = 1;
|
||||
for (auto it = tagCollection.begin(); it != tagCollection.end(); it++) {
|
||||
if (*it != '-' && it != tagCollection.end() - 1) {
|
||||
substring += *it;
|
||||
} else {
|
||||
if (it == tagCollection.end() - 1) {
|
||||
substring += *it;
|
||||
}
|
||||
containers.push_back(substring);
|
||||
if (IsVariantSubtag(substring)) {
|
||||
std::transform(substring.begin(), substring.end(), substring.begin(), AsciiAlphaToLower);
|
||||
if (!uniqueSubtags.insert(substring).second) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
substring.clear();
|
||||
}
|
||||
}
|
||||
bool result = DealwithLanguageTag(containers, address);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string LocaleHelper::ConvertToStdString(const JSHandle<EcmaString> &ecmaStr)
|
||||
{
|
||||
return std::string(ConvertToString(*ecmaStr, StringConvertedUsage::LOGICOPERATION));
|
||||
}
|
||||
|
||||
bool LocaleHelper::DealwithLanguageTag(const std::vector<std::string> &containers, size_t &address)
|
||||
{
|
||||
// The abstract operation returns true if locale can be generated from the ABNF grammar in section 2.1 of the RFC,
|
||||
// starting with Language-Tag, and does not contain duplicate variant or singleton subtags
|
||||
// If language tag is empty, return false.
|
||||
if (containers.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// a. if the first tag is not language, return false.
|
||||
if (!IsLanguageSubtag(containers[0])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// if the tag include language only, like "zh" or "de", return true;
|
||||
if (containers.size() == 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Else, then
|
||||
// if is unique singleton subtag, script and region tag.
|
||||
if (IsExtensionSingleton(containers[1])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IsScriptSubtag(containers[address])) {
|
||||
address++;
|
||||
if (containers.size() == address) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsRegionSubtag(containers[address])) {
|
||||
address++;
|
||||
}
|
||||
|
||||
for (size_t i = address; i < containers.size(); i++) {
|
||||
if (IsExtensionSingleton(containers[i])) {
|
||||
return true;
|
||||
}
|
||||
if (!IsVariantSubtag(containers[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 6.2.4 DefaultLocale ()
|
||||
JSHandle<EcmaString> LocaleHelper::DefaultLocale(JSThread *thread)
|
||||
{
|
||||
icu::Locale defaultLocale;
|
||||
auto globalConst = thread->GlobalConstants();
|
||||
if (strcmp(defaultLocale.getName(), "en_US_POSIX") == 0 || strcmp(defaultLocale.getName(), "c") == 0) {
|
||||
return JSHandle<EcmaString>::Cast(globalConst->GetHandledEnUsString());
|
||||
}
|
||||
if (defaultLocale.isBogus() != 0) {
|
||||
return JSHandle<EcmaString>::Cast(globalConst->GetHandledUndString());
|
||||
}
|
||||
return ToLanguageTag(thread, defaultLocale);
|
||||
}
|
||||
|
||||
void LocaleHelper::HandleLocaleExtension(size_t &start, size_t &extensionEnd, const std::string result, size_t len)
|
||||
{
|
||||
while (start < len - INTL_INDEX_TWO) {
|
||||
if (result[start] != '-') {
|
||||
start++;
|
||||
continue;
|
||||
}
|
||||
if (result[start + INTL_INDEX_TWO] == '-') {
|
||||
extensionEnd = start;
|
||||
break;
|
||||
}
|
||||
start += INTL_INDEX_THREE;
|
||||
}
|
||||
}
|
||||
|
||||
LocaleHelper::ParsedLocale LocaleHelper::HandleLocale(const JSHandle<EcmaString> &localeString)
|
||||
{
|
||||
std::string result = ConvertToStdString(localeString);
|
||||
size_t len = result.size();
|
||||
ParsedLocale parsedResult;
|
||||
|
||||
// a. The single-character subtag ’x’ as the primary subtag indicates
|
||||
// that the language tag consists solely of subtags whose meaning is
|
||||
// defined by private agreement.
|
||||
// b. Extensions cannot be used in tags that are entirely private use.
|
||||
if (IsPrivateSubTag(result, len)) {
|
||||
parsedResult.base = result;
|
||||
return parsedResult;
|
||||
}
|
||||
// If cannot find "-u-", return the whole string as base.
|
||||
size_t foundExtension = result.find("-u-");
|
||||
if (foundExtension == std::string::npos) {
|
||||
parsedResult.base = result;
|
||||
return parsedResult;
|
||||
}
|
||||
// Let privateIndex be Call(%StringProto_indexOf%, foundLocale, « "-x-" »).
|
||||
size_t privateIndex = result.find("-x-");
|
||||
if (privateIndex != std::string::npos && privateIndex < foundExtension) {
|
||||
parsedResult.base = result;
|
||||
return parsedResult;
|
||||
}
|
||||
const std::string basis = result.substr(0, foundExtension);
|
||||
size_t extensionEnd = len;
|
||||
ASSERT(len > INTL_INDEX_TWO);
|
||||
size_t start = foundExtension + 1;
|
||||
HandleLocaleExtension(start, extensionEnd, result, len);
|
||||
const std::string end = result.substr(extensionEnd);
|
||||
parsedResult.base = basis + end;
|
||||
parsedResult.extension = result.substr(foundExtension, extensionEnd - foundExtension);
|
||||
return parsedResult;
|
||||
}
|
||||
|
||||
std::vector<std::string> LocaleHelper::GetAvailableLocales(JSThread *thread, const char *localeKey,
|
||||
const char *localePath)
|
||||
{
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
auto globalConst = thread->GlobalConstants();
|
||||
JSHandle<EcmaString> specialValue = JSHandle<EcmaString>::Cast(globalConst->GetHandledEnUsPosixString());
|
||||
std::string specialString = ConvertToStdString(specialValue);
|
||||
UEnumeration *uenum = uloc_openAvailableByType(ULOC_AVAILABLE_WITH_LEGACY_ALIASES, &status);
|
||||
std::vector<std::string> allLocales;
|
||||
const char *loc = nullptr;
|
||||
for (loc = uenum_next(uenum, nullptr, &status); loc != nullptr; loc = uenum_next(uenum, nullptr, &status)) {
|
||||
ASSERT(U_SUCCESS(status));
|
||||
std::string locStr(loc);
|
||||
std::replace(locStr.begin(), locStr.end(), '_', '-');
|
||||
if (locStr == specialString) {
|
||||
locStr = "en-US-u-va-posix";
|
||||
}
|
||||
|
||||
if (localePath != nullptr || localeKey != nullptr) {
|
||||
icu::Locale locale(locStr.c_str());
|
||||
bool res = false;
|
||||
if (!CheckLocales(locale, localeKey, localePath, res)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
bool isScript = false;
|
||||
allLocales.push_back(locStr);
|
||||
icu::Locale formalLocale = icu::Locale::createCanonical(locStr.c_str());
|
||||
std::string scriptStr = formalLocale.getScript();
|
||||
isScript = scriptStr.empty() ? false : true;
|
||||
if (isScript) {
|
||||
std::string languageStr = formalLocale.getLanguage();
|
||||
std::string countryStr = formalLocale.getCountry();
|
||||
std::string shortLocale = icu::Locale(languageStr.c_str(), countryStr.c_str()).getName();
|
||||
std::replace(shortLocale.begin(), shortLocale.end(), '_', '-');
|
||||
allLocales.push_back(shortLocale);
|
||||
}
|
||||
}
|
||||
uenum_close(uenum);
|
||||
return allLocales;
|
||||
}
|
||||
|
||||
// 9.2.2 BestAvailableLocale ( availableLocales, locale )
|
||||
std::string LocaleHelper::BestAvailableLocale(const std::vector<std::string> &availableLocales,
|
||||
const std::string &locale)
|
||||
{
|
||||
// 1. Let candidate be locale.
|
||||
std::string localeCandidate = locale;
|
||||
std::string undefined = std::string();
|
||||
// 2. Repeat,
|
||||
uint32_t length = availableLocales.size();
|
||||
while (true) {
|
||||
// a. If availableLocales contains an element equal to candidate, return candidate.
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
std::string itemStr = availableLocales[i];
|
||||
if (itemStr == localeCandidate) {
|
||||
return localeCandidate;
|
||||
}
|
||||
}
|
||||
// b. Let pos be the character index of the last occurrence of "-" (U+002D) within candidate.
|
||||
// If that character does not occur, return undefined.
|
||||
size_t pos = localeCandidate.rfind('-');
|
||||
if (pos == std::string::npos) {
|
||||
return undefined;
|
||||
}
|
||||
// c. If pos ≥ 2 and the character "-" occurs at index pos-2 of candidate, decrease pos by 2.
|
||||
if (pos >= INTL_INDEX_TWO && localeCandidate[pos - INTL_INDEX_TWO] == '-') {
|
||||
pos -= INTL_INDEX_TWO;
|
||||
}
|
||||
// d. Let candidate be the substring of candidate from position 0, inclusive, to position pos, exclusive.
|
||||
localeCandidate = localeCandidate.substr(0, pos);
|
||||
}
|
||||
}
|
||||
} // namespace panda::ecmascript::base
|
201
ecmascript/base/locale_helper.h
Normal file
201
ecmascript/base/locale_helper.h
Normal file
@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ECMASCRIPT_BASE_LOCALE_HELPER_H
|
||||
#define ECMASCRIPT_BASE_LOCALE_HELPER_H
|
||||
|
||||
#include "ecmascript/js_handle.h"
|
||||
#include "ecmascript/js_locale.h"
|
||||
|
||||
namespace panda::ecmascript::base {
|
||||
constexpr uint8_t INTL_INDEX_TWO = 2;
|
||||
constexpr uint8_t INTL_INDEX_THREE = 3;
|
||||
constexpr uint8_t INTL_INDEX_FOUR = 4;
|
||||
constexpr uint8_t INTL_INDEX_FIVE = 5;
|
||||
constexpr uint8_t INTL_INDEX_EIGHT = 8;
|
||||
class LocaleHelper {
|
||||
public:
|
||||
struct ParsedLocale {
|
||||
std::string base;
|
||||
std::string extension;
|
||||
};
|
||||
static JSHandle<EcmaString> UStringToString(JSThread *thread, const icu::UnicodeString &string);
|
||||
static JSHandle<EcmaString> UStringToString(JSThread *thread, const icu::UnicodeString &string, int32_t begin,
|
||||
int32_t end);
|
||||
|
||||
// 9.2.1 CanonicalizeLocaleList ( locales )
|
||||
static JSHandle<TaggedArray> CanonicalizeLocaleList(JSThread *thread, const JSHandle<JSTaggedValue> &locales);
|
||||
// 6.2.3 CanonicalizeUnicodeLocaleId ( locale )
|
||||
static JSHandle<EcmaString> CanonicalizeUnicodeLocaleId(JSThread *thread, const JSHandle<EcmaString> &locale);
|
||||
static JSHandle<EcmaString> ToLanguageTag(JSThread *thread, const icu::Locale &locale);
|
||||
static std::vector<std::string> GetAvailableLocales(JSThread *thread, const char *key, const char *path);
|
||||
static bool IsStructurallyValidLanguageTag(const JSHandle<EcmaString> &tag);
|
||||
// 9.2.2 BestAvailableLocale ( availableLocales, locale )
|
||||
static std::string BestAvailableLocale(const std::vector<std::string> &availableLocales,
|
||||
const std::string &locale);
|
||||
|
||||
static JSHandle<EcmaString> DefaultLocale(JSThread *thread);
|
||||
static LocaleHelper::ParsedLocale HandleLocale(const JSHandle<EcmaString> &localeString);
|
||||
static void HandleLocaleExtension(size_t &start, size_t &extensionEnd, const std::string result, size_t len);
|
||||
static std::string ConvertToStdString(const JSHandle<EcmaString> &ecmaStr);
|
||||
private:
|
||||
template<typename T>
|
||||
static JSHandle<TaggedArray> CanonicalizeHelper(JSThread *thread, JSHandle<T> &obj, JSHandle<TaggedArray> &seen);
|
||||
static bool DealwithLanguageTag(const std::vector<std::string> &containers, size_t &address);
|
||||
|
||||
static inline constexpr int AsciiAlphaToLower(uint32_t c)
|
||||
{
|
||||
constexpr uint32_t FLAG = 0x20;
|
||||
return static_cast<int>(c | FLAG);
|
||||
}
|
||||
|
||||
static bool IsLanguageSubtag(const std::string &value)
|
||||
{
|
||||
return IsAlpha(value, INTL_INDEX_TWO, INTL_INDEX_THREE) || IsAlpha(value, INTL_INDEX_FIVE, INTL_INDEX_EIGHT);
|
||||
}
|
||||
|
||||
static bool IsScriptSubtag(const std::string &value)
|
||||
{
|
||||
return IsAlpha(value, INTL_INDEX_FOUR, INTL_INDEX_FOUR);
|
||||
}
|
||||
|
||||
static bool IsRegionSubtag(const std::string &value)
|
||||
{
|
||||
return IsAlpha(value, INTL_INDEX_TWO, INTL_INDEX_TWO) || IsDigit(value, INTL_INDEX_THREE, INTL_INDEX_THREE);
|
||||
}
|
||||
|
||||
static bool IsVariantSubtag(const std::string &value)
|
||||
{
|
||||
return IsThirdDigitAlphanum(value) || IsAlphanum(value, INTL_INDEX_FIVE, INTL_INDEX_EIGHT);
|
||||
}
|
||||
|
||||
static bool IsThirdDigitAlphanum(const std::string &value)
|
||||
{
|
||||
return InRange(value[0], '0', '9') && value.length() == INTL_INDEX_FOUR &&
|
||||
IsAlphanum(value.substr(1), INTL_INDEX_THREE, INTL_INDEX_THREE);
|
||||
}
|
||||
|
||||
static bool IsExtensionSingleton(const std::string &value)
|
||||
{
|
||||
return IsAlphanum(value, 1, 1);
|
||||
}
|
||||
|
||||
static bool IsPrivateSubTag(std::string result, size_t len)
|
||||
{
|
||||
if ((len > 1) && (result[1] == '-')) {
|
||||
ASSERT(result[0] == 'x' || result[0] == 'i');
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
static bool InRange(T value, U start, U end)
|
||||
{
|
||||
ASSERT(start <= end);
|
||||
ASSERT(sizeof(T) >= sizeof(U));
|
||||
return (value >= static_cast<T>(start)) && (value <= static_cast<T>(end));
|
||||
}
|
||||
|
||||
static bool IsAsciiAlpha(char ch)
|
||||
{
|
||||
return InRange(ch, 'A', 'Z') || InRange(ch, 'a', 'z');
|
||||
}
|
||||
|
||||
static bool IsAlpha(const std::string &str, size_t min, size_t max)
|
||||
{
|
||||
if (!InRange(str.length(), min, max)) {
|
||||
return false;
|
||||
}
|
||||
for (char c : str) {
|
||||
if (!IsAsciiAlpha(c)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IsDigit(const std::string &str, size_t min, size_t max)
|
||||
{
|
||||
if (!InRange(str.length(), min, max)) {
|
||||
return false;
|
||||
}
|
||||
for (char i : str) {
|
||||
if (!InRange(i, '0', '9')) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IsAlphanum(const std::string &str, size_t min, size_t max)
|
||||
{
|
||||
if (!InRange(str.length(), min, max)) {
|
||||
return false;
|
||||
}
|
||||
for (char i : str) {
|
||||
if (!IsAsciiAlpha(i) && !InRange(i, '0', '9')) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ValidateOtherTags(const icu::Locale &locale, const char *packageName, const char *key, bool &res)
|
||||
{
|
||||
const char *localeCountry = locale.getCountry();
|
||||
const char *localeScript = locale.getScript();
|
||||
if (localeCountry[0] != '\0' && localeScript[0] != '\0') {
|
||||
std::string removeCountry = locale.getLanguage();
|
||||
removeCountry.append("-");
|
||||
removeCountry.append(localeScript);
|
||||
return CheckLocales(removeCountry.c_str(), key, packageName, res);
|
||||
}
|
||||
if (localeCountry[0] != '\0' || localeScript[0] != '\0') {
|
||||
std::string language = locale.getLanguage();
|
||||
return CheckLocales(language.c_str(), key, packageName, res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool CheckLocales(const icu::Locale &locale, const char *key, const char *packageName, bool &res)
|
||||
{
|
||||
res = false;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
const char *formalLocale = locale.getName();
|
||||
UResourceBundle *localeRes = ures_open(packageName, formalLocale, &status);
|
||||
if (localeRes != nullptr && status == U_ZERO_ERROR) {
|
||||
bool flag = (key == nullptr) ? true : false;
|
||||
if (flag) {
|
||||
res = true;
|
||||
} else {
|
||||
UResourceBundle *keyRes = ures_getByKey(localeRes, key, nullptr, &status);
|
||||
if (keyRes != nullptr && status == U_ZERO_ERROR) {
|
||||
res = true;
|
||||
}
|
||||
ures_close(keyRes);
|
||||
}
|
||||
}
|
||||
ures_close(localeRes);
|
||||
if (res) {
|
||||
return res;
|
||||
} else {
|
||||
ValidateOtherTags(locale, packageName, key, res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif // ECMASCRIPT_BASE_LOCALE_HELPER_H
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "builtins_collator.h"
|
||||
|
||||
#include "ecmascript/base/locale_helper.h"
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/js_collator.h"
|
||||
@ -68,7 +69,7 @@ JSTaggedValue BuiltinsCollator::SupportedLocalesOf(EcmaRuntimeCallInfo *argv)
|
||||
|
||||
// 2. Let requestedLocales be ? CanonicalizeLocaleList(locales).
|
||||
JSHandle<JSTaggedValue> locales = GetCallArg(argv, 0);
|
||||
JSHandle<TaggedArray> requestedLocales = JSLocale::CanonicalizeLocaleList(thread, locales);
|
||||
JSHandle<TaggedArray> requestedLocales = base::LocaleHelper::CanonicalizeLocaleList(thread, locales);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
|
||||
// 3. Return ? SupportedLocales(availableLocales, requestedLocales, options).
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "builtins_date_time_format.h"
|
||||
|
||||
#include "ecmascript/base/locale_helper.h"
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/js_date.h"
|
||||
@ -86,7 +87,7 @@ JSTaggedValue BuiltinsDateTimeFormat::SupportedLocalesOf(EcmaRuntimeCallInfo *ar
|
||||
|
||||
// 2. Let requestedLocales be ? CanonicalizeLocaleList(locales).
|
||||
JSHandle<JSTaggedValue> locales = GetCallArg(argv, 0);
|
||||
JSHandle<TaggedArray> requestedLocales = JSLocale::CanonicalizeLocaleList(thread, locales);
|
||||
JSHandle<TaggedArray> requestedLocales = base::LocaleHelper::CanonicalizeLocaleList(thread, locales);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
|
||||
// 3. Return ? SupportedLocales(availableLocales, requestedLocales, options).
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "builtins_displaynames.h"
|
||||
|
||||
#include "ecmascript/base/locale_helper.h"
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/js_displaynames.h"
|
||||
@ -64,7 +65,7 @@ JSTaggedValue BuiltinsDisplayNames::SupportedLocalesOf(EcmaRuntimeCallInfo *argv
|
||||
|
||||
// 2. Let requestedLocales be ? CanonicaliezLocaleList(locales).
|
||||
JSHandle<JSTaggedValue> locales = GetCallArg(argv, 0);
|
||||
JSHandle<TaggedArray> requestedLocales = JSLocale::CanonicalizeLocaleList(thread, locales);
|
||||
JSHandle<TaggedArray> requestedLocales = base::LocaleHelper::CanonicalizeLocaleList(thread, locales);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
|
||||
// 3. Return ? SupportedLocales(availableLocales, requestedLocales, options).
|
||||
@ -98,7 +99,7 @@ JSTaggedValue BuiltinsDisplayNames::Of(EcmaRuntimeCallInfo *argv)
|
||||
JSHandle<JSDisplayNames> displayNames = JSHandle<JSDisplayNames>::Cast(thisValue);
|
||||
TypednsOption typeOpt = displayNames->GetType();
|
||||
JSHandle<EcmaString> code = JSDisplayNames::CanonicalCodeForDisplayNames(thread, displayNames, typeOpt, codeTemp);
|
||||
std::string codeString = JSLocale::ConvertToStdString(code);
|
||||
std::string codeString = base::LocaleHelper::ConvertToStdString(code);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
if (codeString.size()) {
|
||||
JSHandle<JSTaggedValue> codeStr = JSHandle<JSTaggedValue>::Cast(code);
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "ecmascript/builtins/builtins_intl.h"
|
||||
|
||||
#include "ecmascript/base/locale_helper.h"
|
||||
#include "ecmascript/js_array.h"
|
||||
#include "ecmascript/js_locale.h"
|
||||
#include "ecmascript/js_tagged_value.h"
|
||||
@ -28,7 +29,7 @@ JSTaggedValue BuiltinsIntl::GetCanonicalLocales(EcmaRuntimeCallInfo *argv)
|
||||
|
||||
// 1.Let ll be ? CanonicalizeLocaleList(locales).
|
||||
JSHandle<JSTaggedValue> locales = GetCallArg(argv, 0);
|
||||
JSHandle<TaggedArray> elements = JSLocale::CanonicalizeLocaleList(thread, locales);
|
||||
JSHandle<TaggedArray> elements = base::LocaleHelper::CanonicalizeLocaleList(thread, locales);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
|
||||
// 2.Return CreateArrayFromList(ll).
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "ecmascript/builtins/builtins_list_format.h"
|
||||
|
||||
#include "ecmascript/base/locale_helper.h"
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/js_list_format.h"
|
||||
@ -65,7 +66,7 @@ JSTaggedValue BuiltinsListFormat::SupportedLocalesOf(EcmaRuntimeCallInfo *argv)
|
||||
|
||||
// 2. Let requestedLocales be ? CanonicalizeLocaleList(locales).
|
||||
JSHandle<JSTaggedValue> locales = GetCallArg(argv, 0);
|
||||
JSHandle<TaggedArray> requestedLocales = JSLocale::CanonicalizeLocaleList(thread, locales);
|
||||
JSHandle<TaggedArray> requestedLocales = base::LocaleHelper::CanonicalizeLocaleList(thread, locales);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
|
||||
// 3. Return ? SupportedLocales(availableLocales, requestedLocales, options).
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "ecmascript/builtins/builtins_locale.h"
|
||||
|
||||
#include "ecmascript/base/locale_helper.h"
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/js_locale.h"
|
||||
@ -56,7 +57,7 @@ JSTaggedValue BuiltinsLocale::LocaleConstructor(EcmaRuntimeCallInfo *argv)
|
||||
localeString = JSTaggedValue::ToString(thread, tag);
|
||||
} else {
|
||||
icu::Locale *icuLocale = (JSHandle<JSLocale>::Cast(tag))->GetIcuLocale();
|
||||
localeString = JSLocale::ToLanguageTag(thread, *icuLocale);
|
||||
localeString = base::LocaleHelper::ToLanguageTag(thread, *icuLocale);
|
||||
}
|
||||
// 10. If options is undefined, then
|
||||
// a.Let options be ! ObjectCreate(null).
|
||||
@ -170,7 +171,7 @@ JSTaggedValue BuiltinsLocale::GetBaseName(EcmaRuntimeCallInfo *argv)
|
||||
// 4. Return the substring of locale corresponding to the unicode_language_id production.
|
||||
JSHandle<JSLocale> locale = JSHandle<JSLocale>::Cast(loc);
|
||||
icu::Locale icuLocale = icu::Locale::createFromName(locale->GetIcuLocale()->getBaseName());
|
||||
JSHandle<EcmaString> baseName = JSLocale::ToLanguageTag(thread, icuLocale);
|
||||
JSHandle<EcmaString> baseName = base::LocaleHelper::ToLanguageTag(thread, icuLocale);
|
||||
return baseName.GetTaggedValue();
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "ecmascript/builtins/builtins_number_format.h"
|
||||
|
||||
#include "ecmascript/base/locale_helper.h"
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/js_array.h"
|
||||
@ -88,7 +89,7 @@ JSTaggedValue BuiltinsNumberFormat::SupportedLocalesOf(EcmaRuntimeCallInfo *argv
|
||||
|
||||
// 2. Let requestedLocales be ? CanonicalizeLocaleList(locales).
|
||||
JSHandle<JSTaggedValue> locales = GetCallArg(argv, 0);
|
||||
JSHandle<TaggedArray> requestedLocales = JSLocale::CanonicalizeLocaleList(thread, locales);
|
||||
JSHandle<TaggedArray> requestedLocales = base::LocaleHelper::CanonicalizeLocaleList(thread, locales);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
|
||||
// 3. Return ? SupportedLocales(availableLocales, requestedLocales, options).
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "ecmascript/builtins/builtins_plural_rules.h"
|
||||
|
||||
#include "ecmascript/base/locale_helper.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/js_locale.h"
|
||||
#include "ecmascript/js_object.h"
|
||||
@ -62,7 +63,7 @@ JSTaggedValue BuiltinsPluralRules::SupportedLocalesOf(EcmaRuntimeCallInfo *argv)
|
||||
|
||||
// 2. Let requestedLocales be ? CanonicalizeLocaleList(locales).
|
||||
JSHandle<JSTaggedValue> locales = GetCallArg(argv, 0);
|
||||
JSHandle<TaggedArray> requestedLocales = JSLocale::CanonicalizeLocaleList(thread, locales);
|
||||
JSHandle<TaggedArray> requestedLocales = base::LocaleHelper::CanonicalizeLocaleList(thread, locales);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
|
||||
// 3. Return ? SupportedLocales(availableLocales, requestedLocales, options).
|
||||
|
@ -15,6 +15,8 @@
|
||||
|
||||
#include "ecmascript/builtins/builtins_relative_time_format.h"
|
||||
|
||||
#include "ecmascript/base/locale_helper.h"
|
||||
|
||||
namespace panda::ecmascript::builtins {
|
||||
JSTaggedValue BuiltinsRelativeTimeFormat::RelativeTimeFormatConstructor(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
@ -66,12 +68,13 @@ JSTaggedValue BuiltinsRelativeTimeFormat::SupportedLocalesOf(EcmaRuntimeCallInfo
|
||||
[[maybe_unused]] EcmaHandleScope scope(thread);
|
||||
|
||||
// 1. Let availableLocales be %RelativeTimeFormat%.[[AvailableLocales]].
|
||||
std::vector<std::string> availableStringLocales = JSLocale::GetAvailableLocales(thread, "calendar", nullptr);
|
||||
std::vector<std::string> availableStringLocales =
|
||||
base::LocaleHelper::GetAvailableLocales(thread, "calendar", nullptr);
|
||||
JSHandle<TaggedArray> availableLocales = JSLocale::ConstructLocaleList(thread, availableStringLocales);
|
||||
|
||||
// 2. Let requestedLocales be ? CanonicalizeLocaleList(locales).
|
||||
JSHandle<JSTaggedValue> locales = GetCallArg(argv, 0);
|
||||
JSHandle<TaggedArray> requestedLocales = JSLocale::CanonicalizeLocaleList(thread, locales);
|
||||
JSHandle<TaggedArray> requestedLocales = base::LocaleHelper::CanonicalizeLocaleList(thread, locales);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
|
||||
// 3. Return ? SupportedLocales(availableLocales, requestedLocales, options).
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "ecmascript/base/locale_helper.h"
|
||||
#include "ecmascript/base/number_helper.h"
|
||||
#include "ecmascript/base/string_helper.h"
|
||||
#include "ecmascript/builtins/builtins_json.h"
|
||||
@ -31,7 +32,6 @@
|
||||
#include "ecmascript/js_array.h"
|
||||
#include "ecmascript/js_collator.h"
|
||||
#include "ecmascript/js_hclass.h"
|
||||
#include "ecmascript/js_locale.h"
|
||||
#include "ecmascript/js_object-inl.h"
|
||||
#include "ecmascript/js_primitive_ref.h"
|
||||
#include "ecmascript/js_regexp.h"
|
||||
@ -722,7 +722,7 @@ JSTaggedValue BuiltinsString::Normalize(EcmaRuntimeCallInfo *argv)
|
||||
int32_t option = 0;
|
||||
|
||||
icu::Normalizer::normalize(src, uForm, option, res, errorCode);
|
||||
JSHandle<EcmaString> str = JSLocale::IcuToString(thread, res);
|
||||
JSHandle<EcmaString> str = base::LocaleHelper::UStringToString(thread, res);
|
||||
return JSTaggedValue(*str);
|
||||
}
|
||||
|
||||
@ -1509,29 +1509,29 @@ JSTaggedValue BuiltinsString::ToLocaleLowerCase(EcmaRuntimeCallInfo *argv)
|
||||
EcmaString *result = EcmaStringAccessor::TryToLower(ecmaVm, string);
|
||||
return JSTaggedValue(result);
|
||||
}
|
||||
JSHandle<TaggedArray> requestedLocales = JSLocale::CanonicalizeLocaleList(thread, locales);
|
||||
JSHandle<TaggedArray> requestedLocales = base::LocaleHelper::CanonicalizeLocaleList(thread, locales);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
|
||||
// If requestedLocales is not an empty List, then Let requestedLocale be requestedLocales[0].
|
||||
// Else, Let requestedLocale be DefaultLocale().
|
||||
JSHandle<EcmaString> requestedLocale = JSLocale::DefaultLocale(thread);
|
||||
JSHandle<EcmaString> requestedLocale = base::LocaleHelper::DefaultLocale(thread);
|
||||
if (requestedLocales->GetLength() != 0) {
|
||||
requestedLocale = JSHandle<EcmaString>(thread, requestedLocales->Get(0));
|
||||
}
|
||||
|
||||
// Let noExtensionsLocale be the String value that is requestedLocale with all Unicode locale extension sequences
|
||||
// removed.
|
||||
JSLocale::ParsedLocale noExtensionsLocale = JSLocale::HandleLocale(requestedLocale);
|
||||
base::LocaleHelper::ParsedLocale noExtensionsLocale = base::LocaleHelper::HandleLocale(requestedLocale);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
|
||||
// Let availableLocales be a List with language tags that includes the languages for which the Unicode Character
|
||||
// Database contains language sensitive case mappings. Implementations may add additional language tags
|
||||
// if they support case mapping for additional locales.
|
||||
std::vector<std::string> availableLocales = JSLocale::GetAvailableLocales(thread, nullptr, nullptr);
|
||||
std::vector<std::string> availableLocales = base::LocaleHelper::GetAvailableLocales(thread, nullptr, nullptr);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
|
||||
// Let locale be BestAvailableLocale(availableLocales, noExtensionsLocale).
|
||||
std::string locale = JSLocale::BestAvailableLocale(availableLocales, noExtensionsLocale.base);
|
||||
std::string locale = base::LocaleHelper::BestAvailableLocale(availableLocales, noExtensionsLocale.base);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
|
||||
// If locale is undefined, let locale be "und".
|
||||
@ -1565,29 +1565,29 @@ JSTaggedValue BuiltinsString::ToLocaleUpperCase(EcmaRuntimeCallInfo *argv)
|
||||
|
||||
// Let requestedLocales be ? CanonicalizeLocaleList(locales).
|
||||
JSHandle<JSTaggedValue> locales = GetCallArg(argv, 0);
|
||||
JSHandle<TaggedArray> requestedLocales = JSLocale::CanonicalizeLocaleList(thread, locales);
|
||||
JSHandle<TaggedArray> requestedLocales = base::LocaleHelper::CanonicalizeLocaleList(thread, locales);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
|
||||
// If requestedLocales is not an empty List, then Let requestedLocale be requestedLocales[0].
|
||||
// Else, Let requestedLocale be DefaultLocale().
|
||||
JSHandle<EcmaString> requestedLocale = JSLocale::DefaultLocale(thread);
|
||||
JSHandle<EcmaString> requestedLocale = base::LocaleHelper::DefaultLocale(thread);
|
||||
if (requestedLocales->GetLength() != 0) {
|
||||
requestedLocale = JSHandle<EcmaString>(thread, requestedLocales->Get(0));
|
||||
}
|
||||
|
||||
// Let noExtensionsLocale be the String value that is requestedLocale with all Unicode locale extension sequences
|
||||
// removed.
|
||||
JSLocale::ParsedLocale noExtensionsLocale = JSLocale::HandleLocale(requestedLocale);
|
||||
base::LocaleHelper::ParsedLocale noExtensionsLocale = base::LocaleHelper::HandleLocale(requestedLocale);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
|
||||
// Let availableLocales be a List with language tags that includes the languages for which the Unicode Character
|
||||
// Database contains language sensitive case mappings. Implementations may add additional language tags
|
||||
// if they support case mapping for additional locales.
|
||||
std::vector<std::string> availableLocales = JSLocale::GetAvailableLocales(thread, nullptr, nullptr);
|
||||
std::vector<std::string> availableLocales = base::LocaleHelper::GetAvailableLocales(thread, nullptr, nullptr);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
|
||||
// Let locale be BestAvailableLocale(availableLocales, noExtensionsLocale).
|
||||
std::string locale = JSLocale::BestAvailableLocale(availableLocales, noExtensionsLocale.base);
|
||||
std::string locale = base::LocaleHelper::BestAvailableLocale(availableLocales, noExtensionsLocale.base);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
|
||||
// If locale is undefined, let locale be "und".
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "ecmascript/js_collator.h"
|
||||
|
||||
#include "ecmascript/base/locale_helper.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/mem/c_string.h"
|
||||
#include "ecmascript/mem/barriers-inl.h"
|
||||
@ -40,7 +41,7 @@ JSHandle<TaggedArray> JSCollator::GetAvailableLocales(JSThread *thread)
|
||||
{
|
||||
const char *key = nullptr;
|
||||
const char *path = JSCollator::uIcuDataColl.c_str();
|
||||
std::vector<std::string> availableStringLocales = JSLocale::GetAvailableLocales(thread, key, path);
|
||||
std::vector<std::string> availableStringLocales = base::LocaleHelper::GetAvailableLocales(thread, key, path);
|
||||
JSHandle<TaggedArray> availableLocales = JSLocale::ConstructLocaleList(thread, availableStringLocales);
|
||||
return availableLocales;
|
||||
}
|
||||
@ -73,7 +74,7 @@ JSHandle<JSCollator> JSCollator::InitializeCollator(JSThread *thread,
|
||||
ObjectFactory *factory = ecmaVm->GetFactory();
|
||||
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
|
||||
// 1. Let requestedLocales be ? CanonicalizeLocaleList(locales).
|
||||
JSHandle<TaggedArray> requestedLocales = JSLocale::CanonicalizeLocaleList(thread, locales);
|
||||
JSHandle<TaggedArray> requestedLocales = base::LocaleHelper::CanonicalizeLocaleList(thread, locales);
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSCollator, thread);
|
||||
|
||||
// 2. If options is undefined, then
|
||||
@ -112,7 +113,7 @@ JSHandle<JSCollator> JSCollator::InitializeCollator(JSThread *thread,
|
||||
std::string collationStr;
|
||||
if (!collation->IsUndefined()) {
|
||||
JSHandle<EcmaString> collationEcmaStr = JSHandle<EcmaString>::Cast(collation);
|
||||
collationStr = JSLocale::ConvertToStdString(collationEcmaStr);
|
||||
collationStr = base::LocaleHelper::ConvertToStdString(collationEcmaStr);
|
||||
if (!JSLocale::IsWellAlphaNumList(collationStr)) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "invalid collation", collator);
|
||||
}
|
||||
@ -147,7 +148,7 @@ JSHandle<JSCollator> JSCollator::InitializeCollator(JSThread *thread,
|
||||
ResolvedLocale r =
|
||||
JSLocale::ResolveLocale(thread, availableLocales, requestedLocales, matcher, relevantExtensionKeys);
|
||||
icu::Locale icuLocale = r.localeData;
|
||||
JSHandle<EcmaString> localeStr = JSLocale::ToLanguageTag(thread, icuLocale);
|
||||
JSHandle<EcmaString> localeStr = base::LocaleHelper::ToLanguageTag(thread, icuLocale);
|
||||
collator->SetLocale(thread, localeStr.GetTaggedValue());
|
||||
ASSERT_PRINT(!icuLocale.isBogus(), "icuLocale is bogus");
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "ecmascript/js_date_time_format.h"
|
||||
|
||||
#include "ecmascript/base/locale_helper.h"
|
||||
#include "ecmascript/ecma_macros.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/js_array.h"
|
||||
@ -201,7 +202,7 @@ JSHandle<JSDateTimeFormat> JSDateTimeFormat::InitializeDateTimeFormat(JSThread *
|
||||
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
|
||||
|
||||
// 1. Let requestedLocales be ? CanonicalizeLocaleList(locales).
|
||||
JSHandle<TaggedArray> requestedLocales = JSLocale::CanonicalizeLocaleList(thread, locales);
|
||||
JSHandle<TaggedArray> requestedLocales = base::LocaleHelper::CanonicalizeLocaleList(thread, locales);
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSDateTimeFormat, thread);
|
||||
|
||||
// 2. Let options be ? ToDateTimeOptions(options, "any", "date").
|
||||
@ -227,7 +228,7 @@ JSHandle<JSDateTimeFormat> JSDateTimeFormat::InitializeDateTimeFormat(JSThread *
|
||||
std::string calendarStr;
|
||||
if (!calendar->IsUndefined()) {
|
||||
JSHandle<EcmaString> calendarEcmaStr = JSHandle<EcmaString>::Cast(calendar);
|
||||
calendarStr = JSLocale::ConvertToStdString(calendarEcmaStr);
|
||||
calendarStr = base::LocaleHelper::ConvertToStdString(calendarEcmaStr);
|
||||
if (!JSLocale::IsNormativeCalendar(calendarStr)) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "invalid calendar", dateTimeFormat);
|
||||
}
|
||||
@ -246,7 +247,7 @@ JSHandle<JSDateTimeFormat> JSDateTimeFormat::InitializeDateTimeFormat(JSThread *
|
||||
std::string nsStr;
|
||||
if (!numberingSystem->IsUndefined()) {
|
||||
JSHandle<EcmaString> nsEcmaStr = JSHandle<EcmaString>::Cast(numberingSystem);
|
||||
nsStr = JSLocale::ConvertToStdString(nsEcmaStr);
|
||||
nsStr = base::LocaleHelper::ConvertToStdString(nsEcmaStr);
|
||||
if (!JSLocale::IsWellNumberingSystem(nsStr)) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "invalid numberingSystem", dateTimeFormat);
|
||||
}
|
||||
@ -310,7 +311,7 @@ JSHandle<JSDateTimeFormat> JSDateTimeFormat::InitializeDateTimeFormat(JSThread *
|
||||
if (!operationResult.GetValue()->IsUndefined()) {
|
||||
JSHandle<EcmaString> timezone = JSTaggedValue::ToString(thread, operationResult.GetValue());
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSDateTimeFormat, thread);
|
||||
icuTimeZone = ConstructTimeZone(JSLocale::ConvertToStdString(timezone));
|
||||
icuTimeZone = ConstructTimeZone(base::LocaleHelper::ConvertToStdString(timezone));
|
||||
if (icuTimeZone == nullptr) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "invalid timeZone", dateTimeFormat);
|
||||
}
|
||||
@ -485,7 +486,7 @@ JSHandle<JSDateTimeFormat> JSDateTimeFormat::InitializeDateTimeFormat(JSThread *
|
||||
ASSERT_PRINT(U_SUCCESS(status), "resolvedIcuLocaleCopy set hc failed");
|
||||
}
|
||||
}
|
||||
JSHandle<EcmaString> localeStr = JSLocale::ToLanguageTag(thread, resolvedIcuLocaleCopy);
|
||||
JSHandle<EcmaString> localeStr = base::LocaleHelper::ToLanguageTag(thread, resolvedIcuLocaleCopy);
|
||||
dateTimeFormat->SetLocale(thread, localeStr.GetTaggedValue());
|
||||
|
||||
// Set dateTimeFormat.[[boundFormat]].
|
||||
@ -663,7 +664,7 @@ JSHandle<EcmaString> JSDateTimeFormat::FormatDateTime(JSThread *thread,
|
||||
simpleDateFormat->format(xValue, result);
|
||||
|
||||
// 4. Return result.
|
||||
return JSLocale::IcuToString(thread, result);
|
||||
return base::LocaleHelper::UStringToString(thread, result);
|
||||
}
|
||||
|
||||
// 13.1.8 FormatDateTimeToParts (dateTimeFormat, x)
|
||||
@ -711,8 +712,8 @@ JSHandle<JSArray> JSDateTimeFormat::FormatDateTimeToParts(JSThread *thread,
|
||||
|
||||
// 4. For each part in parts, do
|
||||
for (auto part : parts) {
|
||||
substring.Update(JSLocale::IcuToString(thread, formattedParts, part.fBeginIndex,
|
||||
part.fEndIndex).GetTaggedValue());
|
||||
substring.Update(base::LocaleHelper::UStringToString(thread, formattedParts, part.fBeginIndex,
|
||||
part.fEndIndex).GetTaggedValue());
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSArray, thread);
|
||||
// Let O be ObjectCreate(%ObjectPrototype%).
|
||||
// Perform ! CreateDataPropertyOrThrow(O, "type", part.[[Type]]).
|
||||
@ -874,7 +875,7 @@ void JSDateTimeFormat::ResolvedOptions(JSThread *thread, const JSHandle<JSDateTi
|
||||
(canonicalTimezone == UNICODE_STRING_SIMPLE("Etc/GMT")) != 0) {
|
||||
timezoneValue.Update(globalConst->GetUTCString());
|
||||
} else {
|
||||
timezoneValue.Update(JSLocale::IcuToString(thread, canonicalTimezone).GetTaggedValue());
|
||||
timezoneValue.Update(base::LocaleHelper::UStringToString(thread, canonicalTimezone).GetTaggedValue());
|
||||
}
|
||||
}
|
||||
property = globalConst->GetHandledTimeZoneString();
|
||||
@ -990,7 +991,7 @@ JSHandle<EcmaString> JSDateTimeFormat::NormDateTimeRange(JSThread *thread, const
|
||||
break;
|
||||
}
|
||||
}
|
||||
result = JSLocale::IcuToString(thread, formatResult);
|
||||
result = base::LocaleHelper::UStringToString(thread, formatResult);
|
||||
if (!outputRange) {
|
||||
return FormatDateTime(thread, dtf, x);
|
||||
}
|
||||
@ -1026,7 +1027,7 @@ JSHandle<TaggedArray> JSDateTimeFormat::GainAvailableLocales(JSThread *thread)
|
||||
const char *key = "calendar";
|
||||
const char *path = nullptr;
|
||||
if (dateTimeFormatLocales->IsUndefined()) {
|
||||
std::vector<std::string> availableStringLocales = JSLocale::GetAvailableLocales(thread, key, path);
|
||||
std::vector<std::string> availableStringLocales = base::LocaleHelper::GetAvailableLocales(thread, key, path);
|
||||
JSHandle<TaggedArray> availableLocales = JSLocale::ConstructLocaleList(thread, availableStringLocales);
|
||||
env->SetDateTimeFormatLocales(thread, availableLocales);
|
||||
return availableLocales;
|
||||
@ -1098,8 +1099,8 @@ JSHandle<JSArray> JSDateTimeFormat::ConstructFDateIntervalToJSArray(JSThread *th
|
||||
parts.emplace_back(CommonDateFormatPart(-1, preEndPos, length, index, true));
|
||||
}
|
||||
for (auto part : parts) {
|
||||
substring.Update(JSLocale::IcuToString(thread, formattedValue, part.fBeginIndex,
|
||||
part.fEndIndex).GetTaggedValue());
|
||||
substring.Update(base::LocaleHelper::UStringToString(thread, formattedValue, part.fBeginIndex,
|
||||
part.fEndIndex).GetTaggedValue());
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSArray, thread);
|
||||
JSHandle<JSObject> element;
|
||||
if (part.isPreExist) {
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "ecmascript/base/locale_helper.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/global_env_constants.h"
|
||||
|
||||
@ -83,7 +84,7 @@ JSHandle<TaggedArray> JSDisplayNames::GetAvailableLocales(JSThread *thread)
|
||||
{
|
||||
const char *key = "calendar";
|
||||
const char *path = nullptr;
|
||||
std::vector<std::string> availableStringLocales = JSLocale::GetAvailableLocales(thread, key, path);
|
||||
std::vector<std::string> availableStringLocales = base::LocaleHelper::GetAvailableLocales(thread, key, path);
|
||||
JSHandle<TaggedArray> availableLocales = JSLocale::ConstructLocaleList(thread, availableStringLocales);
|
||||
return availableLocales;
|
||||
}
|
||||
@ -117,7 +118,7 @@ JSHandle<JSDisplayNames> JSDisplayNames::InitializeDisplayNames(JSThread *thread
|
||||
ObjectFactory *factory = ecmaVm->GetFactory();
|
||||
auto globalConst = thread->GlobalConstants();
|
||||
// 3. Let requestedLocales be ? CanonicalizeLocaleList(locales).
|
||||
JSHandle<TaggedArray> requestedLocales = JSLocale::CanonicalizeLocaleList(thread, locales);
|
||||
JSHandle<TaggedArray> requestedLocales = base::LocaleHelper::CanonicalizeLocaleList(thread, locales);
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSDisplayNames, thread);
|
||||
|
||||
// 4. If options is undefined, throw a TypeError exception.
|
||||
@ -192,7 +193,7 @@ JSHandle<JSDisplayNames> JSDisplayNames::InitializeDisplayNames(JSThread *thread
|
||||
displayNames->SetFallback(fallback);
|
||||
|
||||
// 18. Set displayNames.[[Locale]] to the value of r.[[Locale]].
|
||||
JSHandle<EcmaString> localeStr = JSLocale::ToLanguageTag(thread, icuLocale);
|
||||
JSHandle<EcmaString> localeStr = base::LocaleHelper::ToLanguageTag(thread, icuLocale);
|
||||
displayNames->SetLocale(thread, localeStr.GetTaggedValue());
|
||||
// 19. Let dataLocale be r.[[dataLocale]].
|
||||
// 20. Let dataLocaleData be localeData.[[<dataLocale>]].
|
||||
@ -236,7 +237,7 @@ JSHandle<EcmaString> JSDisplayNames::CanonicalCodeForDisplayNames(JSThread *thre
|
||||
if (typeOpt == TypednsOption::LANGUAGE) {
|
||||
// a. If code does not match the unicode_language_id production, throw a RangeError exception.
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
std::string codeSt = JSLocale::ConvertToStdString(code);
|
||||
std::string codeSt = base::LocaleHelper::ConvertToStdString(code);
|
||||
icu::Locale loc = icu::Locale(icu::Locale::forLanguageTag(codeSt, status).getBaseName());
|
||||
std::string checked = loc.toLanguageTag<std::string>(status);
|
||||
if (checked.size() == 0) {
|
||||
@ -248,19 +249,19 @@ JSHandle<EcmaString> JSDisplayNames::CanonicalCodeForDisplayNames(JSThread *thre
|
||||
// b. If IsStructurallyValidLanguageTag(code) is false, throw a RangeError exception.
|
||||
// c. Set code to CanonicalizeUnicodeLocaleId(code).
|
||||
// d. Return code.
|
||||
if (!JSLocale::IsStructurallyValidLanguageTag(code)) {
|
||||
if (!base::LocaleHelper::IsStructurallyValidLanguageTag(code)) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "not a structurally valid", code);
|
||||
}
|
||||
JSHandle<EcmaString> codeStr = JSLocale::CanonicalizeUnicodeLocaleId(thread, code);
|
||||
JSHandle<EcmaString> codeStr = base::LocaleHelper::CanonicalizeUnicodeLocaleId(thread, code);
|
||||
icu::LocaleDisplayNames *icuLocaldisplaynames = displayNames->GetIcuLocaleDisplayNames();
|
||||
icu::UnicodeString result;
|
||||
std::string codeString = JSLocale::ConvertToStdString(codeStr);
|
||||
std::string codeString = base::LocaleHelper::ConvertToStdString(codeStr);
|
||||
icuLocaldisplaynames->languageDisplayName(codeString.c_str(), result);
|
||||
JSHandle<EcmaString> codeResult = JSLocale::IcuToString(thread, result);
|
||||
JSHandle<EcmaString> codeResult = base::LocaleHelper::UStringToString(thread, result);
|
||||
return codeResult;
|
||||
} else if (typeOpt == TypednsOption::REGION) {
|
||||
// a. If code does not match the unicode_region_subtag production, throw a RangeError exception.
|
||||
std::string regionCode = JSLocale::ConvertToStdString(code);
|
||||
std::string regionCode = base::LocaleHelper::ConvertToStdString(code);
|
||||
if (!IsUnicodeRegionSubtag(regionCode)) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "invalid region", code);
|
||||
}
|
||||
@ -269,30 +270,30 @@ JSHandle<EcmaString> JSDisplayNames::CanonicalCodeForDisplayNames(JSThread *thre
|
||||
icu::LocaleDisplayNames *icuLocaldisplaynames = displayNames->GetIcuLocaleDisplayNames();
|
||||
icu::UnicodeString result;
|
||||
icuLocaldisplaynames->regionDisplayName(regionCode.c_str(), result);
|
||||
JSHandle<EcmaString> codeResult = JSLocale::IcuToString(thread, result);
|
||||
JSHandle<EcmaString> codeResult = base::LocaleHelper::UStringToString(thread, result);
|
||||
return codeResult;
|
||||
} else if (typeOpt == TypednsOption::SCRIPT) {
|
||||
std::string scriptCode = JSLocale::ConvertToStdString(code);
|
||||
std::string scriptCode = base::LocaleHelper::ConvertToStdString(code);
|
||||
if (!IsUnicodeScriptSubtag(scriptCode)) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "invalid script", code);
|
||||
}
|
||||
icu::LocaleDisplayNames *icuLocaldisplaynames = displayNames->GetIcuLocaleDisplayNames();
|
||||
icu::UnicodeString result;
|
||||
icuLocaldisplaynames->scriptDisplayName(scriptCode.c_str(), result);
|
||||
JSHandle<EcmaString> codeResult = JSLocale::IcuToString(thread, result);
|
||||
JSHandle<EcmaString> codeResult = base::LocaleHelper::UStringToString(thread, result);
|
||||
return codeResult;
|
||||
}
|
||||
// 4. 4. Assert: type is "currency".
|
||||
// 5. If ! IsWellFormedCurrencyCode(code) is false, throw a RangeError exception.
|
||||
ASSERT(typeOpt == TypednsOption::CURRENCY);
|
||||
std::string cCode = JSLocale::ConvertToStdString(code);
|
||||
std::string cCode = base::LocaleHelper::ConvertToStdString(code);
|
||||
if (!JSLocale::IsWellFormedCurrencyCode(cCode)) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "not a wellformed currency code", code);
|
||||
}
|
||||
icu::LocaleDisplayNames *icuLocaldisplaynames = displayNames->GetIcuLocaleDisplayNames();
|
||||
icu::UnicodeString result;
|
||||
icuLocaldisplaynames->keyValueDisplayName("currency", cCode.c_str(), result);
|
||||
JSHandle<EcmaString> codeResult = JSLocale::IcuToString(thread, result);
|
||||
JSHandle<EcmaString> codeResult = base::LocaleHelper::UStringToString(thread, result);
|
||||
return codeResult;
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#include "ecmascript/base/locale_helper.h"
|
||||
#include "ecmascript/ecma_macros.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/global_env_constants.h"
|
||||
@ -77,7 +78,7 @@ JSHandle<TaggedArray> JSListFormat::GetAvailableLocales(JSThread *thread)
|
||||
}
|
||||
const char *key = "listPattern";
|
||||
const char *path = nullptr;
|
||||
std::vector<std::string> availableStringLocales = JSLocale::GetAvailableLocales(thread, key, path);
|
||||
std::vector<std::string> availableStringLocales = base::LocaleHelper::GetAvailableLocales(thread, key, path);
|
||||
JSHandle<TaggedArray> availableLocales = JSLocale::ConstructLocaleList(thread, availableStringLocales);
|
||||
env->SetListFormatLocales(thread, availableLocales);
|
||||
return availableLocales;
|
||||
@ -95,7 +96,7 @@ JSHandle<JSListFormat> JSListFormat::InitializeListFormat(JSThread *thread,
|
||||
auto globalConst = thread->GlobalConstants();
|
||||
|
||||
// 3. Let requestedLocales be ? CanonicalizeLocaleList(locales).
|
||||
JSHandle<TaggedArray> requestedLocales = JSLocale::CanonicalizeLocaleList(thread, locales);
|
||||
JSHandle<TaggedArray> requestedLocales = base::LocaleHelper::CanonicalizeLocaleList(thread, locales);
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSListFormat, thread);
|
||||
|
||||
// 4. Let options be ? GetOptionsObject(options).
|
||||
@ -132,7 +133,7 @@ JSHandle<JSListFormat> JSListFormat::InitializeListFormat(JSThread *thread,
|
||||
|
||||
// 10. Set listFormat.[[Locale]] to r.[[locale]].
|
||||
icu::Locale icuLocale = r.localeData;
|
||||
JSHandle<EcmaString> localeStr = JSLocale::ToLanguageTag(thread, icuLocale);
|
||||
JSHandle<EcmaString> localeStr = base::LocaleHelper::ToLanguageTag(thread, icuLocale);
|
||||
listFormat->SetLocale(thread, localeStr.GetTaggedValue());
|
||||
|
||||
// 11. Let type be ? GetOption(options, "type", "string", « "conjunction", "disjunction", "unit" », "conjunction").
|
||||
@ -264,7 +265,7 @@ namespace {
|
||||
JSHandle<JSTaggedValue> kValue = JSArray::FastGetPropertyByValue(thread, listArray, k);
|
||||
ASSERT(kValue->IsString());
|
||||
JSHandle<EcmaString> kValueString = JSTaggedValue::ToString(thread, kValue);
|
||||
std::string stdString = JSLocale::ConvertToStdString(kValueString);
|
||||
std::string stdString = base::LocaleHelper::ConvertToStdString(kValueString);
|
||||
icu::StringPiece sp(stdString);
|
||||
icu::UnicodeString uString = icu::UnicodeString::fromUTF8(sp);
|
||||
result.push_back(uString);
|
||||
@ -298,13 +299,13 @@ namespace {
|
||||
int32_t start = cfpo.getStart();
|
||||
int32_t limit = cfpo.getLimit();
|
||||
if (static_cast<UListFormatterField>(fieldId) == ULISTFMT_ELEMENT_FIELD) {
|
||||
JSHandle<EcmaString> substring = JSLocale::IcuToString(thread, listString, start, limit);
|
||||
JSHandle<EcmaString> substring = base::LocaleHelper::UStringToString(thread, listString, start, limit);
|
||||
typeString.Update(globalConst->GetElementString());
|
||||
JSLocale::PutElement(thread, index, receiver, typeString, JSHandle<JSTaggedValue>::Cast(substring));
|
||||
RETURN_IF_ABRUPT_COMPLETION(thread);
|
||||
index++;
|
||||
} else {
|
||||
JSHandle<EcmaString> substring = JSLocale::IcuToString(thread, listString, start, limit);
|
||||
JSHandle<EcmaString> substring = base::LocaleHelper::UStringToString(thread, listString, start, limit);
|
||||
typeString.Update(globalConst->GetLiteralString());
|
||||
JSLocale::PutElement(thread, index, receiver, typeString, JSHandle<JSTaggedValue>::Cast(substring));
|
||||
RETURN_IF_ABRUPT_COMPLETION(thread);
|
||||
@ -370,7 +371,7 @@ JSHandle<EcmaString> JSListFormat::FormatList(JSThread *thread, const JSHandle<J
|
||||
if (U_FAILURE(status)) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "formatted list toString failed", stringValue);
|
||||
}
|
||||
stringValue = JSLocale::IcuToString(thread, result);
|
||||
stringValue = base::LocaleHelper::UStringToString(thread, result);
|
||||
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, stringValue);
|
||||
// 4. Return result
|
||||
return stringValue;
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "ecmascript/js_locale.h"
|
||||
|
||||
#include "ecmascript/base/locale_helper.h"
|
||||
#include "ecmascript/base/string_helper.h"
|
||||
#include "ecmascript/ecma_macros.h"
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
@ -39,87 +40,6 @@
|
||||
|
||||
namespace panda::ecmascript {
|
||||
const std::string LATN_STRING = "latn";
|
||||
// 6.2.2 IsStructurallyValidLanguageTag( locale )
|
||||
bool JSLocale::IsStructurallyValidLanguageTag(const JSHandle<EcmaString> &tag)
|
||||
{
|
||||
std::string tagCollection = ConvertToStdString(tag);
|
||||
std::vector<std::string> containers;
|
||||
std::string substring;
|
||||
std::set<std::string> uniqueSubtags;
|
||||
size_t address = 1;
|
||||
for (auto it = tagCollection.begin(); it != tagCollection.end(); it++) {
|
||||
if (*it != '-' && it != tagCollection.end() - 1) {
|
||||
substring += *it;
|
||||
} else {
|
||||
if (it == tagCollection.end() - 1) {
|
||||
substring += *it;
|
||||
}
|
||||
containers.push_back(substring);
|
||||
if (IsVariantSubtag(substring)) {
|
||||
std::transform(substring.begin(), substring.end(), substring.begin(), AsciiAlphaToLower);
|
||||
if (!uniqueSubtags.insert(substring).second) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
substring.clear();
|
||||
}
|
||||
}
|
||||
bool result = DealwithLanguageTag(containers, address);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string JSLocale::ConvertToStdString(const JSHandle<EcmaString> &ecmaStr)
|
||||
{
|
||||
return std::string(ConvertToString(*ecmaStr, StringConvertedUsage::LOGICOPERATION));
|
||||
}
|
||||
|
||||
// 6.2.3 CanonicalizeUnicodeLocaleId( locale )
|
||||
JSHandle<EcmaString> JSLocale::CanonicalizeUnicodeLocaleId(JSThread *thread, const JSHandle<EcmaString> &locale)
|
||||
{
|
||||
[[maybe_unused]] ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
if (!IsStructurallyValidLanguageTag(locale)) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "invalid locale", factory->GetEmptyString());
|
||||
}
|
||||
|
||||
if (EcmaStringAccessor(locale).GetLength() == 0 || EcmaStringAccessor(locale).IsUtf16()) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "invalid locale", factory->GetEmptyString());
|
||||
}
|
||||
|
||||
std::string localeCStr = ConvertToStdString(locale);
|
||||
std::transform(localeCStr.begin(), localeCStr.end(), localeCStr.begin(), AsciiAlphaToLower);
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
icu::Locale formalLocale = icu::Locale::forLanguageTag(localeCStr.c_str(), status);
|
||||
if ((U_FAILURE(status) != 0) || (formalLocale.isBogus() != 0)) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "invalid locale", factory->GetEmptyString());
|
||||
}
|
||||
|
||||
// Resets the LocaleBuilder to match the locale.
|
||||
// Returns an instance of Locale created from the fields set on this builder.
|
||||
formalLocale = icu::LocaleBuilder().setLocale(formalLocale).build(status);
|
||||
// Canonicalize the locale ID of this object according to CLDR.
|
||||
formalLocale.canonicalize(status);
|
||||
if ((U_FAILURE(status) != 0) || (formalLocale.isBogus() != 0)) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "invalid locale", factory->GetEmptyString());
|
||||
}
|
||||
JSHandle<EcmaString> languageTag = ToLanguageTag(thread, formalLocale);
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(EcmaString, thread);
|
||||
return languageTag;
|
||||
}
|
||||
|
||||
// 6.2.4 DefaultLocale ()
|
||||
JSHandle<EcmaString> JSLocale::DefaultLocale(JSThread *thread)
|
||||
{
|
||||
icu::Locale defaultLocale;
|
||||
auto globalConst = thread->GlobalConstants();
|
||||
if (strcmp(defaultLocale.getName(), "en_US_POSIX") == 0 || strcmp(defaultLocale.getName(), "c") == 0) {
|
||||
return JSHandle<EcmaString>::Cast(globalConst->GetHandledEnUsString());
|
||||
}
|
||||
if (defaultLocale.isBogus() != 0) {
|
||||
return JSHandle<EcmaString>::Cast(globalConst->GetHandledUndString());
|
||||
}
|
||||
return ToLanguageTag(thread, defaultLocale);
|
||||
}
|
||||
|
||||
// 6.4.1 IsValidTimeZoneName ( timeZone )
|
||||
bool JSLocale::IsValidTimeZoneName(const icu::TimeZone &tz)
|
||||
{
|
||||
@ -132,204 +52,6 @@ bool JSLocale::IsValidTimeZoneName(const icu::TimeZone &tz)
|
||||
return (U_SUCCESS(status) != 0) && (canonicalFlag != 0);
|
||||
}
|
||||
|
||||
void JSLocale::HandleLocaleExtension(size_t &start, size_t &extensionEnd,
|
||||
const std::string result, size_t len)
|
||||
{
|
||||
while (start < len - INTL_INDEX_TWO) {
|
||||
if (result[start] != '-') {
|
||||
start++;
|
||||
continue;
|
||||
}
|
||||
if (result[start + INTL_INDEX_TWO] == '-') {
|
||||
extensionEnd = start;
|
||||
break;
|
||||
}
|
||||
start += INTL_INDEX_THREE;
|
||||
}
|
||||
}
|
||||
|
||||
JSLocale::ParsedLocale JSLocale::HandleLocale(const JSHandle<EcmaString> &localeString)
|
||||
{
|
||||
std::string result = ConvertToStdString(localeString);
|
||||
size_t len = result.size();
|
||||
ParsedLocale parsedResult;
|
||||
|
||||
// a. The single-character subtag ’x’ as the primary subtag indicates
|
||||
// that the language tag consists solely of subtags whose meaning is
|
||||
// defined by private agreement.
|
||||
// b. Extensions cannot be used in tags that are entirely private use.
|
||||
if (IsPrivateSubTag(result, len)) {
|
||||
parsedResult.base = result;
|
||||
return parsedResult;
|
||||
}
|
||||
// If cannot find "-u-", return the whole string as base.
|
||||
size_t foundExtension = result.find("-u-");
|
||||
if (foundExtension == std::string::npos) {
|
||||
parsedResult.base = result;
|
||||
return parsedResult;
|
||||
}
|
||||
// Let privateIndex be Call(%StringProto_indexOf%, foundLocale, « "-x-" »).
|
||||
size_t privateIndex = result.find("-x-");
|
||||
if (privateIndex != std::string::npos && privateIndex < foundExtension) {
|
||||
parsedResult.base = result;
|
||||
return parsedResult;
|
||||
}
|
||||
const std::string basis = result.substr(INTL_INDEX_ZERO, foundExtension);
|
||||
size_t extensionEnd = len;
|
||||
ASSERT(len > INTL_INDEX_TWO);
|
||||
size_t start = foundExtension + INTL_INDEX_ONE;
|
||||
HandleLocaleExtension(start, extensionEnd, result, len);
|
||||
const std::string end = result.substr(extensionEnd);
|
||||
parsedResult.base = basis + end;
|
||||
parsedResult.extension = result.substr(foundExtension, extensionEnd - foundExtension);
|
||||
return parsedResult;
|
||||
}
|
||||
|
||||
// 9.2.1 CanonicalizeLocaleList ( locales )
|
||||
JSHandle<TaggedArray> JSLocale::CanonicalizeLocaleList(JSThread *thread, const JSHandle<JSTaggedValue> &locales)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
// 1. If locales is undefined, then
|
||||
// a. Return a new empty List.
|
||||
if (locales->IsUndefined()) {
|
||||
return factory->EmptyArray();
|
||||
}
|
||||
// 2. Let seen be a new empty List.
|
||||
JSHandle<TaggedArray> localeSeen = factory->NewTaggedArray(1);
|
||||
// 3. If Type(locales) is String or Type(locales) is Object and locales has an [[InitializedLocale]] internal slot,
|
||||
// then
|
||||
// a. Let O be CreateArrayFromList(« locales »).
|
||||
// 4. Else,
|
||||
// a.Let O be ? ToObject(locales).
|
||||
if (locales->IsString()) {
|
||||
JSHandle<EcmaString> tag = JSHandle<EcmaString>::Cast(locales);
|
||||
JSHandle<TaggedArray> temp = factory->NewTaggedArray(1);
|
||||
temp->Set(thread, 0, tag.GetTaggedValue());
|
||||
JSHandle<JSArray> obj = JSArray::CreateArrayFromList(thread, temp);
|
||||
JSHandle<TaggedArray> finalSeen = CanonicalizeHelper<JSArray>(thread, obj, localeSeen);
|
||||
return finalSeen;
|
||||
} else if (locales->IsJSLocale()) {
|
||||
JSHandle<EcmaString> tag = JSLocale::ToString(thread, JSHandle<JSLocale>::Cast(locales));
|
||||
JSHandle<TaggedArray> temp = factory->NewTaggedArray(1);
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
|
||||
temp->Set(thread, 0, tag.GetTaggedValue());
|
||||
JSHandle<JSArray> obj = JSArray::CreateArrayFromList(thread, temp);
|
||||
JSHandle<TaggedArray> finalSeen = CanonicalizeHelper<JSArray>(thread, obj, localeSeen);
|
||||
return finalSeen;
|
||||
} else {
|
||||
JSHandle<JSObject> obj = JSTaggedValue::ToObject(thread, locales);
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
|
||||
JSHandle<TaggedArray> finalSeen = CanonicalizeHelper<JSObject>(thread, obj, localeSeen);
|
||||
return finalSeen;
|
||||
}
|
||||
return localeSeen;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
JSHandle<TaggedArray> JSLocale::CanonicalizeHelper(JSThread *thread, JSHandle<T> &obj, JSHandle<TaggedArray> &seen)
|
||||
{
|
||||
OperationResult operationResult = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(obj),
|
||||
thread->GlobalConstants()->GetHandledLengthString());
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
|
||||
JSTaggedNumber len = JSTaggedValue::ToLength(thread, operationResult.GetValue());
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
// 2. Let seen be a new empty List.
|
||||
uint32_t requestedLocalesLen = len.ToUint32();
|
||||
seen = factory->NewTaggedArray(requestedLocalesLen);
|
||||
// 6. Let k be 0.
|
||||
// 7. Repeat, while k < len
|
||||
JSMutableHandle<JSTaggedValue> pk(thread, JSTaggedValue::Undefined());
|
||||
JSMutableHandle<JSTaggedValue> tag(thread, JSTaggedValue::Undefined());
|
||||
uint32_t index = 0;
|
||||
JSHandle<JSTaggedValue> objTagged = JSHandle<JSTaggedValue>::Cast(obj);
|
||||
for (uint32_t k = 0; k < requestedLocalesLen; k++) {
|
||||
// a. Let Pk be ToString(k).
|
||||
JSHandle<JSTaggedValue> kHandle(thread, JSTaggedValue(k));
|
||||
JSHandle<EcmaString> str = JSTaggedValue::ToString(thread, kHandle);
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
|
||||
pk.Update(str.GetTaggedValue());
|
||||
// b. Let kPresent be ? HasProperty(O, Pk).
|
||||
bool kPresent = JSTaggedValue::HasProperty(thread, objTagged, pk);
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
|
||||
|
||||
// c. If kPresent is true, then
|
||||
if (kPresent) {
|
||||
// i. Let kValue be ? Get(O, Pk).
|
||||
OperationResult result = JSTaggedValue::GetProperty(thread, objTagged, pk);
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
|
||||
JSHandle<JSTaggedValue> kValue = result.GetValue();
|
||||
// ii. If Type(kValue) is not String or Object, throw a TypeError exception.
|
||||
if (!kValue->IsString() && !kValue->IsJSObject()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "kValue is not String or Object.", factory->EmptyArray());
|
||||
}
|
||||
// iii. If Type(kValue) is Object and kValue has an [[InitializedLocale]] internal slot, then
|
||||
// 1. Let tag be kValue.[[Locale]].
|
||||
// iv. Else,
|
||||
// 1. Let tag be ? ToString(kValue).
|
||||
if (kValue->IsJSLocale()) {
|
||||
JSHandle<EcmaString> kValueStr = JSLocale::ToString(thread, JSHandle<JSLocale>::Cast(kValue));
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
|
||||
tag.Update(kValueStr.GetTaggedValue());
|
||||
} else {
|
||||
JSHandle<EcmaString> kValueString = JSTaggedValue::ToString(thread, kValue);
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
|
||||
JSHandle<EcmaString> canonicalStr = CanonicalizeUnicodeLocaleId(thread, kValueString);
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
|
||||
tag.Update(canonicalStr.GetTaggedValue());
|
||||
}
|
||||
// vii. If canonicalizedTag is not an element of seen, append canonicalizedTag as the last element of seen.
|
||||
bool isExist = false;
|
||||
uint32_t seenLen = seen->GetLength();
|
||||
for (uint32_t i = 0; i < seenLen; i++) {
|
||||
if (JSTaggedValue::SameValue(seen->Get(thread, i), tag.GetTaggedValue())) {
|
||||
isExist = true;
|
||||
}
|
||||
}
|
||||
if (!isExist) {
|
||||
seen->Set(thread, index++, JSHandle<JSTaggedValue>::Cast(tag));
|
||||
}
|
||||
}
|
||||
// d. Increase k by 1.
|
||||
}
|
||||
// set capacity
|
||||
seen = TaggedArray::SetCapacity(thread, seen, index);
|
||||
// 8. Return seen.
|
||||
return seen;
|
||||
}
|
||||
|
||||
// 9.2.2 BestAvailableLocale ( availableLocales, locale )
|
||||
std::string JSLocale::BestAvailableLocale(const std::vector<std::string> &availableLocales,
|
||||
const std::string &locale)
|
||||
{
|
||||
// 1. Let candidate be locale.
|
||||
std::string localeCandidate = locale;
|
||||
std::string undefined = std::string();
|
||||
// 2. Repeat,
|
||||
uint32_t length = availableLocales.size();
|
||||
while (true) {
|
||||
// a. If availableLocales contains an element equal to candidate, return candidate.
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
std::string itemStr = availableLocales[i];
|
||||
if (itemStr == localeCandidate) {
|
||||
return localeCandidate;
|
||||
}
|
||||
}
|
||||
// b. Let pos be the character index of the last occurrence of "-" (U+002D) within candidate.
|
||||
// If that character does not occur, return undefined.
|
||||
size_t pos = localeCandidate.rfind('-');
|
||||
if (pos == std::string::npos) {
|
||||
return undefined;
|
||||
}
|
||||
// c. If pos ≥ 2 and the character "-" occurs at index pos-2 of candidate, decrease pos by 2.
|
||||
if (pos >= INTL_INDEX_TWO && localeCandidate[pos - INTL_INDEX_TWO] == '-') {
|
||||
pos -= INTL_INDEX_TWO;
|
||||
}
|
||||
// d. Let candidate be the substring of candidate from position 0, inclusive, to position pos, exclusive.
|
||||
localeCandidate = localeCandidate.substr(0, pos);
|
||||
}
|
||||
}
|
||||
|
||||
// 9.2.3 LookupMatcher ( availableLocales, requestedLocales )
|
||||
JSHandle<EcmaString> JSLocale::LookupMatcher(JSThread *thread, const JSHandle<TaggedArray> &availableLocales,
|
||||
const JSHandle<TaggedArray> &requestedLocales)
|
||||
@ -345,9 +67,10 @@ JSHandle<EcmaString> JSLocale::LookupMatcher(JSThread *thread, const JSHandle<Ta
|
||||
locale.Update(requestedLocales->Get(thread, i));
|
||||
// 2. a. Let noExtensionsLocale be the String value that is locale
|
||||
// with all Unicode locale extension sequences removed.
|
||||
ParsedLocale parsedResult = HandleLocale(locale);
|
||||
base::LocaleHelper::ParsedLocale parsedResult = base::LocaleHelper::HandleLocale(locale);
|
||||
// 2. b. Let availableLocale be BestAvailableLocale(availableLocales, noExtensionsLocale).
|
||||
std::string availableLocale = BestAvailableLocale(availableStringLocales, parsedResult.base);
|
||||
std::string availableLocale =
|
||||
base::LocaleHelper::BestAvailableLocale(availableStringLocales, parsedResult.base);
|
||||
// 2. c. If availableLocale is not undefined, append locale to the end of subset.
|
||||
if (!availableLocale.empty()) {
|
||||
result = {std::string(), std::string()};
|
||||
@ -369,7 +92,7 @@ JSHandle<EcmaString> JSLocale::LookupMatcher(JSThread *thread, const JSHandle<Ta
|
||||
// 3. Let defLocale be DefaultLocale();
|
||||
// 4. Set result.[[locale]] to defLocale.
|
||||
// 5. Return result.
|
||||
std::string defLocale = ConvertToStdString(DefaultLocale(thread));
|
||||
std::string defLocale = base::LocaleHelper::ConvertToStdString(base::LocaleHelper::DefaultLocale(thread));
|
||||
result.locale = defLocale;
|
||||
return factory->NewFromStdString(result.locale);
|
||||
}
|
||||
@ -377,7 +100,7 @@ JSHandle<EcmaString> JSLocale::LookupMatcher(JSThread *thread, const JSHandle<Ta
|
||||
icu::LocaleMatcher BuildLocaleMatcher(JSThread *thread, uint32_t *availableLength, UErrorCode *status,
|
||||
const JSHandle<TaggedArray> &availableLocales)
|
||||
{
|
||||
std::string locale = JSLocale::ConvertToStdString(JSLocale::DefaultLocale(thread));
|
||||
std::string locale = base::LocaleHelper::ConvertToStdString(base::LocaleHelper::DefaultLocale(thread));
|
||||
icu::Locale defaultLocale = icu::Locale::forLanguageTag(locale, *status);
|
||||
ASSERT_PRINT(U_SUCCESS(*status), "icu::Locale::forLanguageTag failed");
|
||||
icu::LocaleMatcher::Builder builder;
|
||||
@ -387,7 +110,7 @@ icu::LocaleMatcher BuildLocaleMatcher(JSThread *thread, uint32_t *availableLengt
|
||||
JSMutableHandle<EcmaString> item(thread, JSTaggedValue::Undefined());
|
||||
for (*availableLength = 0; *availableLength < length; ++(*availableLength)) {
|
||||
item.Update(availableLocales->Get(thread, *availableLength));
|
||||
std::string itemStr = JSLocale::ConvertToStdString(item);
|
||||
std::string itemStr = base::LocaleHelper::ConvertToStdString(item);
|
||||
icu::Locale localeForLanguageTag = icu::Locale::forLanguageTag(itemStr, *status);
|
||||
if (U_SUCCESS(*status) != 0) {
|
||||
builder.addSupportedLocale(localeForLanguageTag);
|
||||
@ -414,7 +137,7 @@ JSHandle<EcmaString> JSLocale::BestFitMatcher(JSThread *thread, const JSHandle<T
|
||||
auto bestFit = matcher.getBestMatch(iter, status)->toLanguageTag<std::string>(status);
|
||||
|
||||
if (U_FAILURE(status) != 0) {
|
||||
return DefaultLocale(thread);
|
||||
return base::LocaleHelper::DefaultLocale(thread);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < requestedLocalesLength; ++i) {
|
||||
@ -443,8 +166,9 @@ JSHandle<TaggedArray> JSLocale::LookupSupportedLocales(JSThread *thread, const J
|
||||
// c. If availableLocale is not undefined, append locale to the end of subset.
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
item.Update(requestedLocales->Get(thread, i));
|
||||
ParsedLocale foundationResult = HandleLocale(item);
|
||||
std::string availableLocale = BestAvailableLocale(availableStringLocales, foundationResult.base);
|
||||
base::LocaleHelper::ParsedLocale foundationResult = base::LocaleHelper::HandleLocale(item);
|
||||
std::string availableLocale =
|
||||
base::LocaleHelper::BestAvailableLocale(availableStringLocales, foundationResult.base);
|
||||
if (!availableLocale.empty()) {
|
||||
subset->Set(thread, index++, item.GetTaggedValue());
|
||||
}
|
||||
@ -464,7 +188,7 @@ JSHandle<TaggedArray> JSLocale::BestFitSupportedLocales(JSThread *thread, const
|
||||
ASSERT(U_SUCCESS(status));
|
||||
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<EcmaString> defaultLocale = DefaultLocale(thread);
|
||||
JSHandle<EcmaString> defaultLocale = base::LocaleHelper::DefaultLocale(thread);
|
||||
JSHandle<TaggedArray> result = factory->NewTaggedArray(requestLength);
|
||||
|
||||
uint32_t index = 0;
|
||||
@ -475,7 +199,7 @@ JSHandle<TaggedArray> JSLocale::BestFitSupportedLocales(JSThread *thread, const
|
||||
result->Set(thread, index++, locale.GetTaggedValue());
|
||||
} else {
|
||||
status = U_ZERO_ERROR;
|
||||
std::string localeStr = ConvertToStdString(locale);
|
||||
std::string localeStr = base::LocaleHelper::ConvertToStdString(locale);
|
||||
icu::Locale desired = icu::Locale::forLanguageTag(localeStr, status);
|
||||
auto bestFit = matcher.getBestMatch(desired, status)->toLanguageTag<std::string>(status);
|
||||
if ((U_SUCCESS(status) != 0) &&
|
||||
@ -488,55 +212,6 @@ JSHandle<TaggedArray> JSLocale::BestFitSupportedLocales(JSThread *thread, const
|
||||
return result;
|
||||
}
|
||||
|
||||
JSHandle<EcmaString> JSLocale::ToLanguageTag(JSThread *thread, const icu::Locale &locale)
|
||||
{
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
auto result = locale.toLanguageTag<std::string>(status);
|
||||
bool flag = (U_FAILURE(status) == 0) ? true : false;
|
||||
if (!flag) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "invalid locale", factory->GetEmptyString());
|
||||
}
|
||||
size_t findBeginning = result.find("-u-");
|
||||
std::string finalRes;
|
||||
std::string tempRes;
|
||||
if (findBeginning == std::string::npos) {
|
||||
return factory->NewFromStdString(result);
|
||||
}
|
||||
size_t specialBeginning = findBeginning + INTL_INDEX_THREE;
|
||||
size_t specialCount = 0;
|
||||
while ((specialBeginning < result.size()) && (result[specialBeginning] != '-')) {
|
||||
specialCount++;
|
||||
specialBeginning++;
|
||||
}
|
||||
if (findBeginning != std::string::npos) {
|
||||
// It begin with "-u-xx" or with more elements.
|
||||
tempRes = result.substr(0, findBeginning + INTL_INDEX_THREE + specialCount);
|
||||
if (result.size() <= findBeginning + INTL_INDEX_THREE + specialCount) {
|
||||
return factory->NewFromStdString(result);
|
||||
}
|
||||
std::string leftStr = result.substr(findBeginning + INTL_INDEX_THREE + specialCount + INTL_INDEX_ONE);
|
||||
std::istringstream temp(leftStr);
|
||||
std::string buffer;
|
||||
std::vector<std::string> resContainer;
|
||||
while (getline(temp, buffer, '-')) {
|
||||
if (buffer != "true" && buffer != "yes") {
|
||||
resContainer.push_back(buffer);
|
||||
}
|
||||
}
|
||||
for (auto it = resContainer.begin(); it != resContainer.end(); it++) {
|
||||
std::string tag = "-";
|
||||
tag += *it;
|
||||
finalRes += tag;
|
||||
}
|
||||
}
|
||||
if (!finalRes.empty()) {
|
||||
tempRes += finalRes;
|
||||
}
|
||||
result = tempRes;
|
||||
return factory->NewFromStdString(result);
|
||||
}
|
||||
|
||||
// 9.2.10 SupportedLocales ( availableLocales, requestedLocales, options )
|
||||
JSHandle<JSArray> JSLocale::SupportedLocales(JSThread *thread, const JSHandle<TaggedArray> &availableLocales,
|
||||
const JSHandle<TaggedArray> &requestedLocales,
|
||||
@ -640,7 +315,7 @@ bool JSLocale::GetOptionOfString(JSThread *thread, const JSHandle<JSObject> &opt
|
||||
if (EcmaStringAccessor(valueEStr).IsUtf16()) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "Value out of range for locale options property", false);
|
||||
}
|
||||
*optionValue = JSLocale::ConvertToStdString(valueEStr);
|
||||
*optionValue = base::LocaleHelper::ConvertToStdString(valueEStr);
|
||||
if (values.empty()) {
|
||||
return true;
|
||||
}
|
||||
@ -776,7 +451,7 @@ ResolvedLocale JSLocale::ResolveLocale(JSThread *thread, const JSHandle<TaggedAr
|
||||
// a. Let r be BestFitMatcher(availableLocales, requestedLocales).
|
||||
JSMutableHandle<EcmaString> locale(thread, JSTaggedValue::Undefined());
|
||||
if (availableLocales->GetLength() == 0 && requestedLocales->GetLength() == 0) {
|
||||
locale.Update(DefaultLocale(thread).GetTaggedValue());
|
||||
locale.Update(base::LocaleHelper::DefaultLocale(thread).GetTaggedValue());
|
||||
} else {
|
||||
locale.Update(LookupMatcher(thread, availableLocales, requestedLocales).GetTaggedValue());
|
||||
}
|
||||
@ -785,12 +460,12 @@ ResolvedLocale JSLocale::ResolveLocale(JSThread *thread, const JSHandle<TaggedAr
|
||||
// 5. Let result be a new Record.
|
||||
// 6. Set result.[[dataLocale]] to foundLocale.
|
||||
// 7. Let supportedExtension be "-u".
|
||||
std::string foundLocale = ConvertToStdString(locale);
|
||||
std::string foundLocale = base::LocaleHelper::ConvertToStdString(locale);
|
||||
icu::Locale foundLocaleData = BuildICULocale(foundLocale);
|
||||
ResolvedLocale result;
|
||||
result.localeData = foundLocaleData;
|
||||
JSHandle<EcmaString> tag = ToLanguageTag(thread, foundLocaleData);
|
||||
result.locale = ConvertToStdString(tag);
|
||||
JSHandle<EcmaString> tag = base::LocaleHelper::ToLanguageTag(thread, foundLocaleData);
|
||||
result.locale = base::LocaleHelper::ConvertToStdString(tag);
|
||||
std::string supportedExtension = "-u";
|
||||
icu::LocaleBuilder localeBuilder;
|
||||
localeBuilder.setLocale(foundLocaleData).clearExtensions();
|
||||
@ -894,13 +569,13 @@ ResolvedLocale JSLocale::ResolveLocale(JSThread *thread, const JSHandle<TaggedAr
|
||||
foundLocale = preExtension + supportedExtension + postExtension;
|
||||
}
|
||||
|
||||
tag = ToLanguageTag(thread, foundLocaleData);
|
||||
if (!IsStructurallyValidLanguageTag(tag)) {
|
||||
tag = base::LocaleHelper::ToLanguageTag(thread, foundLocaleData);
|
||||
if (!base::LocaleHelper::IsStructurallyValidLanguageTag(tag)) {
|
||||
result.extensions.erase(result.extensions.begin(), result.extensions.end());
|
||||
result.locale = foundLocale;
|
||||
}
|
||||
tag = CanonicalizeUnicodeLocaleId(thread, tag);
|
||||
foundLocale = ConvertToStdString(tag);
|
||||
tag = base::LocaleHelper::CanonicalizeUnicodeLocaleId(thread, tag);
|
||||
foundLocale = base::LocaleHelper::ConvertToStdString(tag);
|
||||
}
|
||||
|
||||
// 10. Set result.[[locale]] to foundLocale.
|
||||
@ -936,18 +611,6 @@ JSHandle<TaggedArray> JSLocale::ConstructLocaleList(JSThread *thread,
|
||||
return locales;
|
||||
}
|
||||
|
||||
JSHandle<EcmaString> JSLocale::IcuToString(JSThread *thread, const icu::UnicodeString &string)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
return factory->NewFromUtf16(reinterpret_cast<const uint16_t *>(string.getBuffer()), string.length());
|
||||
}
|
||||
|
||||
JSHandle<EcmaString> JSLocale::IcuToString(JSThread *thread, const icu::UnicodeString &string, int32_t begin,
|
||||
int32_t end)
|
||||
{
|
||||
return IcuToString(thread, string.tempSubStringBetween(begin, end));
|
||||
}
|
||||
|
||||
std::string JSLocale::GetNumberingSystem(const icu::Locale &icuLocale)
|
||||
{
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
@ -1060,8 +723,8 @@ bool JSLocale::ApplyOptionsToTag(JSThread *thread, const JSHandle<EcmaString> &t
|
||||
if (*tag == *(factory->GetEmptyString())) {
|
||||
return false;
|
||||
}
|
||||
// 2. If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception.
|
||||
if (!IsStructurallyValidLanguageTag(tag)) {
|
||||
// 2. If base::LocaleHelper::IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception.
|
||||
if (!base::LocaleHelper::IsStructurallyValidLanguageTag(tag)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1073,7 +736,8 @@ bool JSLocale::ApplyOptionsToTag(JSThread *thread, const JSHandle<EcmaString> &t
|
||||
// 4. If language is not undefined, then
|
||||
// a. If language does not match the unicode_language_subtag production, throw a RangeError exception.
|
||||
if (!tagElements.language->IsUndefined()) {
|
||||
std::string languageStr = ConvertToStdString(JSHandle<EcmaString>::Cast(tagElements.language));
|
||||
std::string languageStr =
|
||||
base::LocaleHelper::ConvertToStdString(JSHandle<EcmaString>::Cast(tagElements.language));
|
||||
if (languageStr[INTL_INDEX_ZERO] == '\0' ||
|
||||
IsAlpha(languageStr, INTL_INDEX_FOUR, INTL_INDEX_FOUR)) {
|
||||
return false;
|
||||
@ -1089,7 +753,8 @@ bool JSLocale::ApplyOptionsToTag(JSThread *thread, const JSHandle<EcmaString> &t
|
||||
// 6. If script is not undefined, then
|
||||
// a. If script does not match the unicode_script_subtag production, throw a RangeError exception.
|
||||
if (!tagElements.script->IsUndefined()) {
|
||||
std::string scriptStr = JSLocale::ConvertToStdString((JSHandle<EcmaString>::Cast(tagElements.script)));
|
||||
std::string scriptStr =
|
||||
base::LocaleHelper::ConvertToStdString((JSHandle<EcmaString>::Cast(tagElements.script)));
|
||||
if (scriptStr[INTL_INDEX_ZERO] == '\0') {
|
||||
return false;
|
||||
}
|
||||
@ -1104,7 +769,7 @@ bool JSLocale::ApplyOptionsToTag(JSThread *thread, const JSHandle<EcmaString> &t
|
||||
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
|
||||
|
||||
if (!tagElements.region->IsUndefined()) {
|
||||
std::string regionStr = ConvertToStdString(JSHandle<EcmaString>::Cast(tagElements.region));
|
||||
std::string regionStr = base::LocaleHelper::ConvertToStdString(JSHandle<EcmaString>::Cast(tagElements.region));
|
||||
if (regionStr[INTL_INDEX_ZERO] == '\0') {
|
||||
return false;
|
||||
}
|
||||
@ -1115,7 +780,7 @@ bool JSLocale::ApplyOptionsToTag(JSThread *thread, const JSHandle<EcmaString> &t
|
||||
bool BuildOptionsTags(const JSHandle<EcmaString> &tag, icu::LocaleBuilder *builder, JSHandle<JSTaggedValue> language,
|
||||
JSHandle<JSTaggedValue> script, JSHandle<JSTaggedValue> region)
|
||||
{
|
||||
std::string tagStr = JSLocale::ConvertToStdString(tag);
|
||||
std::string tagStr = base::LocaleHelper::ConvertToStdString(tag);
|
||||
int32_t len = static_cast<int32_t>(tagStr.length());
|
||||
ASSERT(len > 0);
|
||||
builder->setLanguageTag({ tagStr.c_str(), len });
|
||||
@ -1128,7 +793,7 @@ bool BuildOptionsTags(const JSHandle<EcmaString> &tag, icu::LocaleBuilder *build
|
||||
builder->setLocale(locale);
|
||||
|
||||
if (!language->IsUndefined()) {
|
||||
std::string languageStr = JSLocale::ConvertToStdString(JSHandle<EcmaString>::Cast(language));
|
||||
std::string languageStr = base::LocaleHelper::ConvertToStdString(JSHandle<EcmaString>::Cast(language));
|
||||
builder->setLanguage(languageStr);
|
||||
builder->build(status);
|
||||
if ((U_FAILURE(status) != 0)) {
|
||||
@ -1137,7 +802,7 @@ bool BuildOptionsTags(const JSHandle<EcmaString> &tag, icu::LocaleBuilder *build
|
||||
}
|
||||
|
||||
if (!script->IsUndefined()) {
|
||||
std::string scriptStr = JSLocale::ConvertToStdString((JSHandle<EcmaString>::Cast(script)));
|
||||
std::string scriptStr = base::LocaleHelper::ConvertToStdString((JSHandle<EcmaString>::Cast(script)));
|
||||
builder->setScript(scriptStr);
|
||||
builder->build(status);
|
||||
if ((U_FAILURE(status) != 0)) {
|
||||
@ -1146,7 +811,7 @@ bool BuildOptionsTags(const JSHandle<EcmaString> &tag, icu::LocaleBuilder *build
|
||||
}
|
||||
|
||||
if (!region->IsUndefined()) {
|
||||
std::string regionStr = JSLocale::ConvertToStdString(JSHandle<EcmaString>::Cast(region));
|
||||
std::string regionStr = base::LocaleHelper::ConvertToStdString(JSHandle<EcmaString>::Cast(region));
|
||||
builder->setRegion(regionStr);
|
||||
builder->build(status);
|
||||
if ((U_FAILURE(status) != 0)) {
|
||||
@ -1255,53 +920,6 @@ JSHandle<JSLocale> JSLocale::InitializeLocale(JSThread *thread, const JSHandle<J
|
||||
return locale;
|
||||
}
|
||||
|
||||
bool JSLocale::DealwithLanguageTag(const std::vector<std::string> &containers, size_t &address)
|
||||
{
|
||||
// The abstract operation returns true if locale can be generated from the ABNF grammar in section 2.1 of the RFC,
|
||||
// starting with Language-Tag, and does not contain duplicate variant or singleton subtags
|
||||
// If language tag is empty, return false.
|
||||
if (containers.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// a. if the first tag is not language, return false.
|
||||
if (!IsLanguageSubtag(containers[0])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// if the tag include language only, like "zh" or "de", return true;
|
||||
if (containers.size() == 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Else, then
|
||||
// if is unique singleton subtag, script and region tag.
|
||||
if (IsExtensionSingleton(containers[1])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IsScriptSubtag(containers[address])) {
|
||||
address++;
|
||||
if (containers.size() == address) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsRegionSubtag(containers[address])) {
|
||||
address++;
|
||||
}
|
||||
|
||||
for (size_t i = address; i < containers.size(); i++) {
|
||||
if (IsExtensionSingleton(containers[i])) {
|
||||
return true;
|
||||
}
|
||||
if (!IsVariantSubtag(containers[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int ConvertValue(const UErrorCode &status, std::string &value, const std::string &key)
|
||||
{
|
||||
if (status == U_ILLEGAL_ARGUMENT_ERROR || value.empty()) {
|
||||
@ -1345,51 +963,10 @@ JSHandle<EcmaString> JSLocale::ToString(JSThread *thread, const JSHandle<JSLocal
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
return factory->GetEmptyString();
|
||||
}
|
||||
JSHandle<EcmaString> result = ToLanguageTag(thread, *icuLocale);
|
||||
JSHandle<EcmaString> result = base::LocaleHelper::ToLanguageTag(thread, *icuLocale);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::string> JSLocale::GetAvailableLocales(JSThread *thread, const char *localeKey, const char *localePath)
|
||||
{
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
auto globalConst = thread->GlobalConstants();
|
||||
JSHandle<EcmaString> specialValue = JSHandle<EcmaString>::Cast(globalConst->GetHandledEnUsPosixString());
|
||||
std::string specialString = ConvertToStdString(specialValue);
|
||||
UEnumeration *uenum = uloc_openAvailableByType(ULOC_AVAILABLE_WITH_LEGACY_ALIASES, &status);
|
||||
std::vector<std::string> allLocales;
|
||||
const char *loc = nullptr;
|
||||
for (loc = uenum_next(uenum, nullptr, &status); loc != nullptr; loc = uenum_next(uenum, nullptr, &status)) {
|
||||
ASSERT(U_SUCCESS(status));
|
||||
std::string locStr(loc);
|
||||
std::replace(locStr.begin(), locStr.end(), '_', '-');
|
||||
if (locStr == specialString) {
|
||||
locStr = "en-US-u-va-posix";
|
||||
}
|
||||
|
||||
if (localePath != nullptr || localeKey != nullptr) {
|
||||
icu::Locale locale(locStr.c_str());
|
||||
bool res = false;
|
||||
if (!CheckLocales(locale, localeKey, localePath, res)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
bool isScript = false;
|
||||
allLocales.push_back(locStr);
|
||||
icu::Locale formalLocale = icu::Locale::createCanonical(locStr.c_str());
|
||||
std::string scriptStr = formalLocale.getScript();
|
||||
isScript = scriptStr.empty() ? false : true;
|
||||
if (isScript) {
|
||||
std::string languageStr = formalLocale.getLanguage();
|
||||
std::string countryStr = formalLocale.getCountry();
|
||||
std::string shortLocale = icu::Locale(languageStr.c_str(), countryStr.c_str()).getName();
|
||||
std::replace(shortLocale.begin(), shortLocale.end(), '_', '-');
|
||||
allLocales.push_back(shortLocale);
|
||||
}
|
||||
}
|
||||
uenum_close(uenum);
|
||||
return allLocales;
|
||||
}
|
||||
|
||||
std::vector<std::string> JSLocale::GetAvailableStringLocales(JSThread *thread,
|
||||
const JSHandle<TaggedArray> &availableLocales)
|
||||
{
|
||||
@ -1398,7 +975,7 @@ std::vector<std::string> JSLocale::GetAvailableStringLocales(JSThread *thread,
|
||||
uint32_t availablecalesLength = availableLocales->GetLength();
|
||||
for (uint32_t i = 0; i < availablecalesLength; i++) {
|
||||
availableItem.Update(availableLocales->Get(thread, i));
|
||||
availableStringLocales.emplace_back(ConvertToStdString(availableItem));
|
||||
availableStringLocales.emplace_back(base::LocaleHelper::ConvertToStdString(availableItem));
|
||||
}
|
||||
return availableStringLocales;
|
||||
}
|
||||
|
@ -147,11 +147,6 @@ struct TagElements {
|
||||
|
||||
class JSLocale : public JSObject {
|
||||
public:
|
||||
struct ParsedLocale {
|
||||
std::string base;
|
||||
std::string extension;
|
||||
};
|
||||
|
||||
static JSLocale *Cast(TaggedObject *object)
|
||||
{
|
||||
ASSERT(JSTaggedValue(object).IsJSLocale());
|
||||
@ -184,32 +179,12 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
static std::string ConvertToStdString(const JSHandle<EcmaString> &ecmaStr);
|
||||
|
||||
// 6.2.2 IsStructurallyValidLanguageTag ( locale )
|
||||
static bool IsStructurallyValidLanguageTag(const JSHandle<EcmaString> &tag);
|
||||
|
||||
static bool DealwithLanguageTag(const std::vector<std::string> &containers, size_t &address);
|
||||
|
||||
// 6.2.3 CanonicalizeUnicodeLocaleId ( locale )
|
||||
static JSHandle<EcmaString> CanonicalizeUnicodeLocaleId(JSThread *thread, const JSHandle<EcmaString> &locale);
|
||||
|
||||
// 6.2.4 DefaultLocale ()
|
||||
static JSHandle<EcmaString> DefaultLocale(JSThread *thread);
|
||||
|
||||
// 6.4.1 IsValidTimeZoneName ( timeZone )
|
||||
static bool IsValidTimeZoneName(const icu::TimeZone &tz);
|
||||
|
||||
// 9.2.1 CanonicalizeLocaleList ( locales )
|
||||
static JSHandle<TaggedArray> CanonicalizeLocaleList(JSThread *thread, const JSHandle<JSTaggedValue> &locales);
|
||||
|
||||
template<typename T>
|
||||
static JSHandle<TaggedArray> CanonicalizeHelper(JSThread *thread, JSHandle<T> &obj, JSHandle<TaggedArray> &seen);
|
||||
|
||||
// 9.2.2 BestAvailableLocale ( availableLocales, locale )
|
||||
static std::string BestAvailableLocale(const std::vector<std::string> &availableLocales,
|
||||
const std::string &locale);
|
||||
|
||||
// 9.2.3 LookupMatcher ( availableLocales, requestedLocales )
|
||||
static JSHandle<EcmaString> LookupMatcher(JSThread *thread, const JSHandle<TaggedArray> &availableLocales,
|
||||
const JSHandle<TaggedArray> &requestedLocales);
|
||||
@ -261,7 +236,7 @@ public:
|
||||
// i. If values does not contain an element equal to value, throw a RangeError exception.
|
||||
JSHandle<EcmaString> valueEStr = JSTaggedValue::ToString(thread, value);
|
||||
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, T::EXCEPTION);
|
||||
std::string valueStr = ConvertToStdString(valueEStr);
|
||||
std::string valueStr = std::string(ConvertToString(*valueEStr, StringConvertedUsage::LOGICOPERATION));
|
||||
int existIdx = -1;
|
||||
if (!enumValues.empty()) {
|
||||
size_t strValuesSize = strValues.size();
|
||||
@ -498,13 +473,6 @@ public:
|
||||
return res;
|
||||
}
|
||||
|
||||
static JSHandle<EcmaString> IcuToString(JSThread *thread, const icu::UnicodeString &string);
|
||||
|
||||
static JSHandle<EcmaString> IcuToString(JSThread *thread, const icu::UnicodeString &string, int32_t begin,
|
||||
int32_t end);
|
||||
|
||||
static std::vector<std::string> GetAvailableLocales(JSThread *thread, const char *key, const char *path);
|
||||
|
||||
static std::vector<std::string> GetAvailableStringLocales(JSThread *thread,
|
||||
const JSHandle<TaggedArray> &availableLocales);
|
||||
|
||||
@ -512,8 +480,6 @@ public:
|
||||
const JSHandle<JSTaggedValue> &fieldTypeString,
|
||||
const JSHandle<JSTaggedValue> &value);
|
||||
|
||||
static JSHandle<EcmaString> ToLanguageTag(JSThread *thread, const icu::Locale &locale);
|
||||
|
||||
static std::string GetNumberingSystem(const icu::Locale &icuLocale);
|
||||
|
||||
static bool IsWellFormedCurrencyCode(const std::string ¤cy);
|
||||
@ -530,10 +496,6 @@ public:
|
||||
static JSHandle<EcmaString> NormalizeKeywordValue(JSThread *thread, const JSHandle<JSLocale> &locale,
|
||||
const std::string &key);
|
||||
|
||||
static void HandleLocaleExtension(size_t &start, size_t &extensionEnd, const std::string result, size_t len);
|
||||
|
||||
static ParsedLocale HandleLocale(const JSHandle<EcmaString> &locale);
|
||||
|
||||
static JSHandle<EcmaString> ToString(JSThread *thread, const JSHandle<JSLocale> &locale);
|
||||
|
||||
// 12.1.1 SetNumberFormatDigitOptions ( intlObj, options, mnfdDefault, mxfdDefault, notation )
|
||||
|
@ -288,7 +288,7 @@ FractionDigitsOption SetNumberFormatUnitOptions(JSThread *thread,
|
||||
if (EcmaStringAccessor(currencyStr).IsUtf16()) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "not a utf-8", fractionDigitsOption);
|
||||
}
|
||||
std::string currencyCStr = JSLocale::ConvertToStdString(currencyStr);
|
||||
std::string currencyCStr = base::LocaleHelper::ConvertToStdString(currencyStr);
|
||||
if (!JSLocale::IsWellFormedCurrencyCode(currencyCStr)) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "not a wellformed code", fractionDigitsOption);
|
||||
}
|
||||
@ -334,7 +334,7 @@ FractionDigitsOption SetNumberFormatUnitOptions(JSThread *thread,
|
||||
if (EcmaStringAccessor(unitStr).IsUtf16()) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "Unit input is illegal", fractionDigitsOption);
|
||||
}
|
||||
std::string str = JSLocale::ConvertToStdString(unitStr);
|
||||
std::string str = base::LocaleHelper::ConvertToStdString(unitStr);
|
||||
if (!IsWellFormedUnitIdentifier(str, icuUnit, icuPerUnit)) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "Unit input is illegal", fractionDigitsOption);
|
||||
}
|
||||
@ -362,7 +362,7 @@ FractionDigitsOption SetNumberFormatUnitOptions(JSThread *thread,
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
if (style == StyleOption::CURRENCY) {
|
||||
JSHandle<EcmaString> currencyStr = JSHandle<EcmaString>::Cast(currency);
|
||||
std::string currencyCStr = JSLocale::ConvertToStdString(currencyStr);
|
||||
std::string currencyCStr = base::LocaleHelper::ConvertToStdString(currencyStr);
|
||||
std::transform(currencyCStr.begin(), currencyCStr.end(), currencyCStr.begin(), toupper);
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<JSTaggedValue> currencyValue = JSHandle<JSTaggedValue>::Cast(factory->NewFromStdString(currencyCStr));
|
||||
@ -442,7 +442,7 @@ void JSNumberFormat::InitializeNumberFormat(JSThread *thread, const JSHandle<JSN
|
||||
EcmaVM *ecmaVm = thread->GetEcmaVM();
|
||||
ObjectFactory *factory = ecmaVm->GetFactory();
|
||||
// 1. Let requestedLocales be ? CanonicalizeLocaleList(locales).
|
||||
JSHandle<TaggedArray> requestedLocales = JSLocale::CanonicalizeLocaleList(thread, locales);
|
||||
JSHandle<TaggedArray> requestedLocales = base::LocaleHelper::CanonicalizeLocaleList(thread, locales);
|
||||
|
||||
// 2. If options is undefined, then
|
||||
// a. Let options be ObjectCreate(null).
|
||||
@ -481,7 +481,7 @@ void JSNumberFormat::InitializeNumberFormat(JSThread *thread, const JSHandle<JSN
|
||||
if (EcmaStringAccessor(numberingSystemEcmaString).IsUtf16()) {
|
||||
THROW_ERROR(thread, ErrorType::RANGE_ERROR, "invalid numberingSystem");
|
||||
}
|
||||
numberingSystemStr = JSLocale::ConvertToStdString(numberingSystemEcmaString);
|
||||
numberingSystemStr = base::LocaleHelper::ConvertToStdString(numberingSystemEcmaString);
|
||||
if (!JSLocale::IsNormativeNumberingSystem(numberingSystemStr)) {
|
||||
THROW_ERROR(thread, ErrorType::RANGE_ERROR, "invalid numberingSystem");
|
||||
}
|
||||
@ -503,7 +503,7 @@ void JSNumberFormat::InitializeNumberFormat(JSThread *thread, const JSHandle<JSN
|
||||
|
||||
// 12. Set numberFormat.[[Locale]] to r.[[locale]].
|
||||
icu::Locale icuLocale = r.localeData;
|
||||
JSHandle<EcmaString> localeStr = JSLocale::ToLanguageTag(thread, icuLocale);
|
||||
JSHandle<EcmaString> localeStr = base::LocaleHelper::ToLanguageTag(thread, icuLocale);
|
||||
numberFormat->SetLocale(thread, localeStr.GetTaggedValue());
|
||||
|
||||
// Set numberingSystemStr to UnicodeKeyWord "nu"
|
||||
@ -738,7 +738,7 @@ JSHandle<JSTaggedValue> JSNumberFormat::FormatNumeric(JSThread *thread,
|
||||
JSHandle<JSTaggedValue> errorResult(thread, JSTaggedValue::Exception());
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "formatted number toString failed", errorResult);
|
||||
}
|
||||
JSHandle<EcmaString> stringValue = JSLocale::IcuToString(thread, result);
|
||||
JSHandle<EcmaString> stringValue = base::LocaleHelper::UStringToString(thread, result);
|
||||
return JSHandle<JSTaggedValue>::Cast(stringValue);
|
||||
}
|
||||
|
||||
@ -789,14 +789,15 @@ void GroupToParts(JSThread *thread, const icu::number::FormattedNumber &formatte
|
||||
// so add a literal type with value of formattedText.sub(0, start)
|
||||
// Special case when fieldId is UNUM_GROUPING_SEPARATOR_FIELD
|
||||
if (static_cast<UNumberFormatFields>(fieldId) == UNUM_GROUPING_SEPARATOR_FIELD) {
|
||||
JSHandle<EcmaString> substring = JSLocale::IcuToString(thread, formattedText, previousLimit, start);
|
||||
JSHandle<EcmaString> substring =
|
||||
base::LocaleHelper::UStringToString(thread, formattedText, previousLimit, start);
|
||||
typeString.Update(globalConst->GetIntegerString());
|
||||
JSLocale::PutElement(thread, index, receiver, typeString, JSHandle<JSTaggedValue>::Cast(substring));
|
||||
RETURN_IF_ABRUPT_COMPLETION(thread);
|
||||
index++;
|
||||
{
|
||||
typeString.Update(JSLocale::GetNumberFieldType(thread, x, fieldId).GetTaggedValue());
|
||||
substring = JSLocale::IcuToString(thread, formattedText, start, limit);
|
||||
substring = base::LocaleHelper::UStringToString(thread, formattedText, start, limit);
|
||||
JSLocale::PutElement(thread, index, receiver, typeString, JSHandle<JSTaggedValue>::Cast(substring));
|
||||
RETURN_IF_ABRUPT_COMPLETION(thread);
|
||||
index++;
|
||||
@ -806,7 +807,8 @@ void GroupToParts(JSThread *thread, const icu::number::FormattedNumber &formatte
|
||||
previousLimit = limit;
|
||||
continue;
|
||||
} else if (start > previousLimit) {
|
||||
JSHandle<EcmaString> substring = JSLocale::IcuToString(thread, formattedText, previousLimit, start);
|
||||
JSHandle<EcmaString> substring =
|
||||
base::LocaleHelper::UStringToString(thread, formattedText, previousLimit, start);
|
||||
JSLocale::PutElement(thread, index, receiver, typeString, JSHandle<JSTaggedValue>::Cast(substring));
|
||||
RETURN_IF_ABRUPT_COMPLETION(thread);
|
||||
index++;
|
||||
@ -821,7 +823,7 @@ void GroupToParts(JSThread *thread, const icu::number::FormattedNumber &formatte
|
||||
} else {
|
||||
typeString.Update(JSLocale::GetNumberFieldType(thread, x, fieldId).GetTaggedValue());
|
||||
}
|
||||
JSHandle<EcmaString> substring = JSLocale::IcuToString(thread, formattedText, start, limit);
|
||||
JSHandle<EcmaString> substring = base::LocaleHelper::UStringToString(thread, formattedText, start, limit);
|
||||
JSLocale::PutElement(thread, index, receiver, typeString, JSHandle<JSTaggedValue>::Cast(substring));
|
||||
RETURN_IF_ABRUPT_COMPLETION(thread);
|
||||
index++;
|
||||
@ -832,7 +834,7 @@ void GroupToParts(JSThread *thread, const icu::number::FormattedNumber &formatte
|
||||
if (formattedText.length() > previousLimit) {
|
||||
typeString.Update(globalConst->GetLiteralString());
|
||||
JSHandle<EcmaString> substring =
|
||||
JSLocale::IcuToString(thread, formattedText, previousLimit, formattedText.length());
|
||||
base::LocaleHelper::UStringToString(thread, formattedText, previousLimit, formattedText.length());
|
||||
JSLocale::PutElement(thread, index, receiver, typeString, JSHandle<JSTaggedValue>::Cast(substring));
|
||||
}
|
||||
}
|
||||
@ -900,7 +902,7 @@ JSHandle<TaggedArray> JSNumberFormat::GetAvailableLocales(JSThread *thread)
|
||||
}
|
||||
const char *key = "NumberElements";
|
||||
const char *path = nullptr;
|
||||
std::vector<std::string> availableStringLocales = JSLocale::GetAvailableLocales(thread, key, path);
|
||||
std::vector<std::string> availableStringLocales = base::LocaleHelper::GetAvailableLocales(thread, key, path);
|
||||
JSHandle<TaggedArray> availableLocales = JSLocale::ConstructLocaleList(thread, availableStringLocales);
|
||||
env->SetNumberFormatLocales(thread, availableLocales);
|
||||
return availableLocales;
|
||||
|
@ -16,6 +16,7 @@
|
||||
#ifndef ECMASCRIPT_JS_NUMBER_FORMAT_H
|
||||
#define ECMASCRIPT_JS_NUMBER_FORMAT_H
|
||||
|
||||
#include "ecmascript/base/locale_helper.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/js_array.h"
|
||||
#include "ecmascript/js_hclass.h"
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "ecmascript/js_plural_rules.h"
|
||||
|
||||
#include "ecmascript/base/locale_helper.h"
|
||||
#include "ecmascript/ecma_macros.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/global_env_constants.h"
|
||||
@ -154,7 +155,7 @@ JSHandle<JSPluralRules> JSPluralRules::InitializePluralRules(JSThread *thread,
|
||||
auto globalConst = thread->GlobalConstants();
|
||||
|
||||
// 1. Let requestedLocales be ? CanonicalizeLocaleList(locales).
|
||||
JSHandle<TaggedArray> requestedLocales = JSLocale::CanonicalizeLocaleList(thread, locales);
|
||||
JSHandle<TaggedArray> requestedLocales = base::LocaleHelper::CanonicalizeLocaleList(thread, locales);
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSPluralRules, thread);
|
||||
|
||||
// 2&3. If options is undefined, then Let options be ObjectCreate(null). else Let options be ? ToObject(options).
|
||||
@ -254,7 +255,7 @@ JSHandle<JSPluralRules> JSPluralRules::InitializePluralRules(JSThread *thread,
|
||||
SetIcuNumberFormatter(thread, pluralRules, icuNumberFormatter, JSPluralRules::FreeIcuNumberFormatter);
|
||||
|
||||
// 12. Set pluralRules.[[Locale]] to the value of r.[[locale]].
|
||||
JSHandle<EcmaString> localeStr = JSLocale::ToLanguageTag(thread, icuLocale);
|
||||
JSHandle<EcmaString> localeStr = base::LocaleHelper::ToLanguageTag(thread, icuLocale);
|
||||
pluralRules->SetLocale(thread, localeStr.GetTaggedValue());
|
||||
|
||||
// 13. Return pluralRules.
|
||||
@ -360,7 +361,7 @@ void JSPluralRules::ResolvedOptions(JSThread *thread, const JSHandle<JSPluralRul
|
||||
for (int32_t i = 0; i < count; i++) {
|
||||
const icu::UnicodeString *category = categories->snext(status);
|
||||
ASSERT(U_SUCCESS(status));
|
||||
JSHandle<EcmaString> value = JSLocale::IcuToString(thread, *category);
|
||||
JSHandle<EcmaString> value = base::LocaleHelper::UStringToString(thread, *category);
|
||||
pluralCategories->Set(thread, i, value);
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ JSHandle<JSRelativeTimeFormat> JSRelativeTimeFormat::InitializeRelativeTimeForma
|
||||
ObjectFactory *factory = ecmaVm->GetFactory();
|
||||
|
||||
// 1.Let requestedLocales be ? CanonicalizeLocaleList(locales).
|
||||
JSHandle<TaggedArray> requestedLocales = JSLocale::CanonicalizeLocaleList(thread, locales);
|
||||
JSHandle<TaggedArray> requestedLocales = base::LocaleHelper::CanonicalizeLocaleList(thread, locales);
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSRelativeTimeFormat, thread);
|
||||
|
||||
// 2&3. If options is undefined, then Let options be ObjectCreate(null). else Let options be ? ToObject(options).
|
||||
@ -63,7 +63,7 @@ JSHandle<JSRelativeTimeFormat> JSRelativeTimeFormat::InitializeRelativeTimeForma
|
||||
if (EcmaStringAccessor(numberingSystemString).IsUtf16()) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "invalid numberingSystem", relativeTimeFormat);
|
||||
}
|
||||
numberingSystemStdStr = JSLocale::ConvertToStdString(numberingSystemString);
|
||||
numberingSystemStdStr = base::LocaleHelper::ConvertToStdString(numberingSystemString);
|
||||
if (!JSLocale::IsNormativeNumberingSystem(numberingSystemStdStr)) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "invalid numberingSystem", relativeTimeFormat);
|
||||
}
|
||||
@ -76,7 +76,8 @@ JSHandle<JSRelativeTimeFormat> JSRelativeTimeFormat::InitializeRelativeTimeForma
|
||||
if (requestedLocales->GetLength() == 0) {
|
||||
availableLocales = factory->EmptyArray();
|
||||
} else {
|
||||
std::vector<std::string> availableStringLocales = JSLocale::GetAvailableLocales(thread, "calendar", nullptr);
|
||||
std::vector<std::string> availableStringLocales =
|
||||
base::LocaleHelper::GetAvailableLocales(thread, "calendar", nullptr);
|
||||
availableLocales = JSLocale::ConstructLocaleList(thread, availableStringLocales);
|
||||
}
|
||||
std::set<std::string> relevantExtensionKeys{"nu"};
|
||||
@ -86,7 +87,7 @@ JSHandle<JSRelativeTimeFormat> JSRelativeTimeFormat::InitializeRelativeTimeForma
|
||||
icu::Locale icuLocale = r.localeData;
|
||||
|
||||
// 12. Let locale be r.[[Locale]].
|
||||
JSHandle<EcmaString> localeStr = JSLocale::ToLanguageTag(thread, icuLocale);
|
||||
JSHandle<EcmaString> localeStr = base::LocaleHelper::ToLanguageTag(thread, icuLocale);
|
||||
|
||||
// 13. Set relativeTimeFormat.[[Locale]] to locale.
|
||||
relativeTimeFormat->SetLocale(thread, localeStr.GetTaggedValue());
|
||||
@ -414,7 +415,8 @@ void FormatToArray(JSThread *thread, const JSHandle<JSArray> &array,
|
||||
// so add a literal type with value of formattedText.sub(0, start)
|
||||
if (start > previousLimit) {
|
||||
typeString.Update(globalConst->GetLiteralString());
|
||||
JSHandle<EcmaString> substring = JSLocale::IcuToString(thread, formattedText, previousLimit, start);
|
||||
JSHandle<EcmaString> substring =
|
||||
base::LocaleHelper::UStringToString(thread, formattedText, previousLimit, start);
|
||||
JSLocale::PutElement(thread, index++, array, typeString, JSHandle<JSTaggedValue>::Cast(substring));
|
||||
RETURN_IF_ABRUPT_COMPLETION(thread);
|
||||
}
|
||||
@ -423,7 +425,8 @@ void FormatToArray(JSThread *thread, const JSHandle<JSArray> &array,
|
||||
for (auto it = separatorFields.begin(); it != separatorFields.end(); it++) {
|
||||
if (it->first > start) {
|
||||
// Add Integer type element
|
||||
JSHandle<EcmaString> resString = JSLocale::IcuToString(thread, formattedText, start, it->first);
|
||||
JSHandle<EcmaString> resString =
|
||||
base::LocaleHelper::UStringToString(thread, formattedText, start, it->first);
|
||||
typeString.Update(
|
||||
JSLocale::GetNumberFieldType(thread, taggedValue.GetTaggedValue(), fieldId).GetTaggedValue());
|
||||
JSHandle<JSObject> record =
|
||||
@ -432,7 +435,7 @@ void FormatToArray(JSThread *thread, const JSHandle<JSArray> &array,
|
||||
JSObject::CreateDataPropertyOrThrow(thread, record, unitString, JSHandle<JSTaggedValue>::Cast(unit));
|
||||
RETURN_IF_ABRUPT_COMPLETION(thread);
|
||||
// Add Group type element
|
||||
resString = JSLocale::IcuToString(thread, formattedText, it->first, it->second);
|
||||
resString = base::LocaleHelper::UStringToString(thread, formattedText, it->first, it->second);
|
||||
typeString.Update(JSLocale::GetNumberFieldType(thread, taggedValue.GetTaggedValue(),
|
||||
UNUM_GROUPING_SEPARATOR_FIELD).GetTaggedValue());
|
||||
record =
|
||||
@ -444,7 +447,7 @@ void FormatToArray(JSThread *thread, const JSHandle<JSArray> &array,
|
||||
}
|
||||
}
|
||||
// Add current field unit
|
||||
JSHandle<EcmaString> subString = JSLocale::IcuToString(thread, formattedText, start, limit);
|
||||
JSHandle<EcmaString> subString = base::LocaleHelper::UStringToString(thread, formattedText, start, limit);
|
||||
typeString.Update(JSLocale::GetNumberFieldType(thread, taggedValue.GetTaggedValue(), fieldId).GetTaggedValue());
|
||||
JSHandle<JSObject> record =
|
||||
JSLocale::PutElement(thread, index++, array, typeString, JSHandle<JSTaggedValue>::Cast(subString));
|
||||
@ -458,7 +461,7 @@ void FormatToArray(JSThread *thread, const JSHandle<JSArray> &array,
|
||||
if (formattedText.length() > previousLimit) {
|
||||
typeString.Update(globalConst->GetLiteralString());
|
||||
JSHandle<EcmaString> substring =
|
||||
JSLocale::IcuToString(thread, formattedText, previousLimit, formattedText.length());
|
||||
base::LocaleHelper::UStringToString(thread, formattedText, previousLimit, formattedText.length());
|
||||
JSLocale::PutElement(thread, index, array, typeString, JSHandle<JSTaggedValue>::Cast(substring));
|
||||
RETURN_IF_ABRUPT_COMPLETION(thread);
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "unicode/reldatefmt.h"
|
||||
|
||||
#include "ecmascript/base/locale_helper.h"
|
||||
#include "ecmascript/base/number_helper.h"
|
||||
#include "ecmascript/common.h"
|
||||
#include "ecmascript/ecma_macros.h"
|
||||
|
@ -121,6 +121,7 @@ host_unittest_action("EcmaVm_002_Test") {
|
||||
"js_proxy_test.cpp",
|
||||
"js_regexp_iterator_test.cpp",
|
||||
"js_relative_time_format_test.cpp",
|
||||
"locale_helper_test.cpp",
|
||||
]
|
||||
|
||||
configs = [
|
||||
|
@ -13,6 +13,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecmascript/base/locale_helper.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/js_date.h"
|
||||
#include "ecmascript/js_date_time_format.h"
|
||||
@ -21,6 +22,7 @@
|
||||
|
||||
using namespace panda;
|
||||
using namespace panda::ecmascript;
|
||||
using namespace panda::ecmascript::base;
|
||||
|
||||
namespace panda::test {
|
||||
class JSDateTimeFormatTest : public testing::Test {
|
||||
@ -218,7 +220,7 @@ HWTEST_F_L0(JSDateTimeFormatTest, InitializeDateTimeFormat)
|
||||
|
||||
JSHandle<JSTaggedValue> localeTagVal(thread, dtf->GetLocale());
|
||||
JSHandle<EcmaString> localeEcmaStr = JSHandle<EcmaString>::Cast(localeTagVal);
|
||||
std::string localeStr = JSLocale::ConvertToStdString(localeEcmaStr);
|
||||
std::string localeStr = LocaleHelper::ConvertToStdString(localeEcmaStr);
|
||||
EXPECT_STREQ(localeStr.c_str(), "zh-Hans-CN-u-ca-chinese");
|
||||
}
|
||||
|
||||
@ -249,17 +251,17 @@ HWTEST_F_L0(JSDateTimeFormatTest, ToDateTimeOptions_001)
|
||||
options = JSDateTimeFormat::ToDateTimeOptions(
|
||||
thread, JSHandle<JSTaggedValue>::Cast(options), RequiredOption::ANY, DefaultsOption::ALL); // test "ALL"
|
||||
auto yearEcmaStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, yearKey).GetValue());
|
||||
EXPECT_STREQ(JSLocale::ConvertToStdString(yearEcmaStr).c_str(), "numeric");
|
||||
EXPECT_STREQ(LocaleHelper::ConvertToStdString(yearEcmaStr).c_str(), "numeric");
|
||||
auto monthEcmaStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, monthKey).GetValue());
|
||||
EXPECT_STREQ(JSLocale::ConvertToStdString(monthEcmaStr).c_str(), "numeric");
|
||||
EXPECT_STREQ(LocaleHelper::ConvertToStdString(monthEcmaStr).c_str(), "numeric");
|
||||
auto dayEcmaStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, dayKey).GetValue());
|
||||
EXPECT_STREQ(JSLocale::ConvertToStdString(dayEcmaStr).c_str(), "numeric");
|
||||
EXPECT_STREQ(LocaleHelper::ConvertToStdString(dayEcmaStr).c_str(), "numeric");
|
||||
auto hourEcmaStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, hourKey).GetValue());
|
||||
EXPECT_STREQ(JSLocale::ConvertToStdString(hourEcmaStr).c_str(), "numeric");
|
||||
EXPECT_STREQ(LocaleHelper::ConvertToStdString(hourEcmaStr).c_str(), "numeric");
|
||||
auto minuteEcmaStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, minuteKey).GetValue());
|
||||
EXPECT_STREQ(JSLocale::ConvertToStdString(minuteEcmaStr).c_str(), "numeric");
|
||||
EXPECT_STREQ(LocaleHelper::ConvertToStdString(minuteEcmaStr).c_str(), "numeric");
|
||||
auto secondEcmaStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, secondKey).GetValue());
|
||||
EXPECT_STREQ(JSLocale::ConvertToStdString(secondEcmaStr).c_str(), "numeric");
|
||||
EXPECT_STREQ(LocaleHelper::ConvertToStdString(secondEcmaStr).c_str(), "numeric");
|
||||
}
|
||||
|
||||
HWTEST_F_L0(JSDateTimeFormatTest, ToDateTimeOptions_002)
|
||||
@ -300,24 +302,24 @@ HWTEST_F_L0(JSDateTimeFormatTest, ToDateTimeOptions_002)
|
||||
options = JSDateTimeFormat::ToDateTimeOptions(
|
||||
thread, JSHandle<JSTaggedValue>::Cast(options), RequiredOption::ANY, DefaultsOption::ALL); // test "ANY"
|
||||
auto weekdayStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, weekdayKey).GetValue());
|
||||
EXPECT_STREQ(JSLocale::ConvertToStdString(weekdayStr).c_str(), "narrow");
|
||||
EXPECT_STREQ(LocaleHelper::ConvertToStdString(weekdayStr).c_str(), "narrow");
|
||||
auto yearStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, yearKey).GetValue());
|
||||
EXPECT_STREQ(JSLocale::ConvertToStdString(yearStr).c_str(), "2-digit");
|
||||
EXPECT_STREQ(LocaleHelper::ConvertToStdString(yearStr).c_str(), "2-digit");
|
||||
auto monthStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, monthKey).GetValue());
|
||||
EXPECT_STREQ(JSLocale::ConvertToStdString(monthStr).c_str(), "2-digit");
|
||||
EXPECT_STREQ(LocaleHelper::ConvertToStdString(monthStr).c_str(), "2-digit");
|
||||
auto dayStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, dayKey).GetValue());
|
||||
EXPECT_STREQ(JSLocale::ConvertToStdString(dayStr).c_str(), "2-digit");
|
||||
EXPECT_STREQ(LocaleHelper::ConvertToStdString(dayStr).c_str(), "2-digit");
|
||||
|
||||
auto dayPeriodStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, dayPeriodKey).GetValue());
|
||||
EXPECT_STREQ(JSLocale::ConvertToStdString(dayPeriodStr).c_str(), "narrow");
|
||||
EXPECT_STREQ(LocaleHelper::ConvertToStdString(dayPeriodStr).c_str(), "narrow");
|
||||
auto hourStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, hourKey).GetValue());
|
||||
EXPECT_STREQ(JSLocale::ConvertToStdString(hourStr).c_str(), "2-digit");
|
||||
EXPECT_STREQ(LocaleHelper::ConvertToStdString(hourStr).c_str(), "2-digit");
|
||||
auto minuteStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, minuteKey).GetValue());
|
||||
EXPECT_STREQ(JSLocale::ConvertToStdString(minuteStr).c_str(), "2-digit");
|
||||
EXPECT_STREQ(LocaleHelper::ConvertToStdString(minuteStr).c_str(), "2-digit");
|
||||
auto secondStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, secondKey).GetValue());
|
||||
EXPECT_STREQ(JSLocale::ConvertToStdString(secondStr).c_str(), "2-digit");
|
||||
EXPECT_STREQ(LocaleHelper::ConvertToStdString(secondStr).c_str(), "2-digit");
|
||||
auto fracSecStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, fracSecKey).GetValue());
|
||||
EXPECT_STREQ(JSLocale::ConvertToStdString(fracSecStr).c_str(), "1");
|
||||
EXPECT_STREQ(LocaleHelper::ConvertToStdString(fracSecStr).c_str(), "1");
|
||||
}
|
||||
|
||||
JSHandle<JSDateTimeFormat> CreateDateTimeFormatTest(JSThread *thread, icu::Locale icuLocale, JSHandle<JSObject> options)
|
||||
@ -368,9 +370,9 @@ HWTEST_F_L0(JSDateTimeFormatTest, FormatDateTime_001)
|
||||
// When the option is blank, the default format is "yyyy/MM/dd", the year, month and day are all numeric,
|
||||
// because the default option in initialization is "DefaultsOption::DATE".
|
||||
JSHandle<EcmaString> dateTimeEcamStr1 = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp1);
|
||||
EXPECT_STREQ(JSLocale::ConvertToStdString(dateTimeEcamStr1).c_str(), "2022/5/25");
|
||||
EXPECT_STREQ(LocaleHelper::ConvertToStdString(dateTimeEcamStr1).c_str(), "2022/5/25");
|
||||
JSHandle<EcmaString> dateTimeEcamStr2 = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp2);
|
||||
EXPECT_STREQ(JSLocale::ConvertToStdString(dateTimeEcamStr2).c_str(), "2022/5/30");
|
||||
EXPECT_STREQ(LocaleHelper::ConvertToStdString(dateTimeEcamStr2).c_str(), "2022/5/30");
|
||||
}
|
||||
|
||||
HWTEST_F_L0(JSDateTimeFormatTest, FormatDateTime_002)
|
||||
@ -398,9 +400,9 @@ HWTEST_F_L0(JSDateTimeFormatTest, FormatDateTime_002)
|
||||
|
||||
// Format to include all options by "DefaultsOption::ALL".
|
||||
JSHandle<EcmaString> dateTimeEcamStr1 = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp1);
|
||||
EXPECT_STREQ(JSLocale::ConvertToStdString(dateTimeEcamStr1).c_str(), "2022/5/25 上午11:09:34");
|
||||
EXPECT_STREQ(LocaleHelper::ConvertToStdString(dateTimeEcamStr1).c_str(), "2022/5/25 上午11:09:34");
|
||||
JSHandle<EcmaString> dateTimeEcamStr2 = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp2);
|
||||
EXPECT_STREQ(JSLocale::ConvertToStdString(dateTimeEcamStr2).c_str(), "2022/5/30 下午10:30:12");
|
||||
EXPECT_STREQ(LocaleHelper::ConvertToStdString(dateTimeEcamStr2).c_str(), "2022/5/30 下午10:30:12");
|
||||
}
|
||||
|
||||
HWTEST_F_L0(JSDateTimeFormatTest, FormatDateTime_003)
|
||||
@ -444,9 +446,9 @@ HWTEST_F_L0(JSDateTimeFormatTest, FormatDateTime_003)
|
||||
double timeStamp2 = 1653921012999; // test "2022-05-30 22:30:12.999"
|
||||
|
||||
JSHandle<EcmaString> dateTimeEcamStr1 = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp1);
|
||||
EXPECT_STREQ(JSLocale::ConvertToStdString(dateTimeEcamStr1).c_str(), "22年05月25日星期三 上午11:09:34.000");
|
||||
EXPECT_STREQ(LocaleHelper::ConvertToStdString(dateTimeEcamStr1).c_str(), "22年05月25日星期三 上午11:09:34.000");
|
||||
JSHandle<EcmaString> dateTimeEcamStr2 = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp2);
|
||||
EXPECT_STREQ(JSLocale::ConvertToStdString(dateTimeEcamStr2).c_str(), "22年05月30日星期一 晚上10:30:12.999");
|
||||
EXPECT_STREQ(LocaleHelper::ConvertToStdString(dateTimeEcamStr2).c_str(), "22年05月30日星期一 晚上10:30:12.999");
|
||||
}
|
||||
|
||||
HWTEST_F_L0(JSDateTimeFormatTest, FormatDateTime_004)
|
||||
@ -490,10 +492,10 @@ HWTEST_F_L0(JSDateTimeFormatTest, FormatDateTime_004)
|
||||
double timeStamp2 = 1653921012999; // test "2022-05-30 22:30:12.999"
|
||||
|
||||
JSHandle<EcmaString> dateTimeEcamStr1 = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp1);
|
||||
EXPECT_STREQ(JSLocale::ConvertToStdString(dateTimeEcamStr1).c_str(),
|
||||
EXPECT_STREQ(LocaleHelper::ConvertToStdString(dateTimeEcamStr1).c_str(),
|
||||
"Wednesday, 05/25/22, 11:09:34.000 in the morning");
|
||||
JSHandle<EcmaString> dateTimeEcamStr2 = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp2);
|
||||
EXPECT_STREQ(JSLocale::ConvertToStdString(dateTimeEcamStr2).c_str(),
|
||||
EXPECT_STREQ(LocaleHelper::ConvertToStdString(dateTimeEcamStr2).c_str(),
|
||||
"Monday, 05/30/22, 10:30:12.999 at night");
|
||||
}
|
||||
|
||||
@ -502,7 +504,7 @@ std::string GetDateTimePartStringTest(JSThread *thread, JSHandle<JSTaggedValue>
|
||||
JSHandle<JSObject> partObj = JSHandle<JSObject>::Cast(part);
|
||||
JSHandle<JSTaggedValue> partValue = JSObject::GetProperty(thread, partObj, key).GetValue();
|
||||
JSHandle<EcmaString> partEcmaStr = JSHandle<EcmaString>::Cast(partValue);
|
||||
std::string partStr = JSLocale::ConvertToStdString(partEcmaStr);
|
||||
std::string partStr = LocaleHelper::ConvertToStdString(partEcmaStr);
|
||||
return partStr;
|
||||
}
|
||||
|
||||
@ -538,7 +540,7 @@ HWTEST_F_L0(JSDateTimeFormatTest, FormatDateTimeToParts_001)
|
||||
double timeStamp = 1653448174123; // test "2022-05-25 11:09:34.123"
|
||||
// Use default date time format and format date and time to parts.
|
||||
JSHandle<EcmaString> dateTimeEcamStr1 = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp);
|
||||
EXPECT_STREQ(JSLocale::ConvertToStdString(dateTimeEcamStr1).c_str(), "2022/5/25");
|
||||
EXPECT_STREQ(LocaleHelper::ConvertToStdString(dateTimeEcamStr1).c_str(), "2022/5/25");
|
||||
JSHandle<JSArray> dateTimeArray1 = JSDateTimeFormat::FormatDateTimeToParts(thread, dtf, timeStamp);
|
||||
auto year = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(dateTimeArray1), 0).GetValue();
|
||||
auto literal1 = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(dateTimeArray1), 1).GetValue();
|
||||
@ -597,7 +599,7 @@ HWTEST_F_L0(JSDateTimeFormatTest, FormatDateTimeToParts_002)
|
||||
thread, JSHandle<JSTaggedValue>::Cast(options), RequiredOption::ANY, DefaultsOption::ALL);
|
||||
JSHandle<JSDateTimeFormat> dtf = CreateDateTimeFormatTest(thread, icuLocale, options);
|
||||
JSHandle<EcmaString> dateTimeEcamStr = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp);
|
||||
EXPECT_STREQ(JSLocale::ConvertToStdString(dateTimeEcamStr).c_str(), "22年05月25日星期三 上午11:09:34.123");
|
||||
EXPECT_STREQ(LocaleHelper::ConvertToStdString(dateTimeEcamStr).c_str(), "22年05月25日星期三 上午11:09:34.123");
|
||||
|
||||
JSHandle<JSArray> dateTimeArray = JSDateTimeFormat::FormatDateTimeToParts(thread, dtf, timeStamp);
|
||||
auto year = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(dateTimeArray), 0).GetValue();
|
||||
@ -669,7 +671,7 @@ HWTEST_F_L0(JSDateTimeFormatTest, GainAvailableLocales)
|
||||
|
||||
const char *key = "calendar";
|
||||
const char *path = nullptr;
|
||||
std::vector<std::string> availableStringLocales = JSLocale::GetAvailableLocales(thread, key, path);
|
||||
std::vector<std::string> availableStringLocales = base::LocaleHelper::GetAvailableLocales(thread, key, path);
|
||||
JSHandle<TaggedArray> availableLocales = JSLocale::ConstructLocaleList(thread, availableStringLocales);
|
||||
env->SetDateTimeFormatLocales(thread, availableLocales);
|
||||
JSHandle<TaggedArray> gainLocales1 = JSDateTimeFormat::GainAvailableLocales(thread);
|
||||
|
@ -14,6 +14,8 @@
|
||||
*/
|
||||
|
||||
#include "ecmascript/js_displaynames.h"
|
||||
|
||||
#include "ecmascript/base/locale_helper.h"
|
||||
#include "ecmascript/tests/test_helper.h"
|
||||
|
||||
using namespace panda;
|
||||
@ -83,7 +85,8 @@ HWTEST_F_L0(JSDisplayNamesTest, GetIcuLocaleDisplayNames)
|
||||
thread, displayNames, iculocaledisplaynames, JSDisplayNames::FreeIcuLocaleDisplayNames);
|
||||
icu::LocaleDisplayNames *resultIculocaledisplaynames = displayNames->GetIcuLocaleDisplayNames();
|
||||
EXPECT_TRUE(iculocaledisplaynames == resultIculocaledisplaynames);
|
||||
JSHandle<EcmaString> localeStr = JSLocale::ToLanguageTag(thread, resultIculocaledisplaynames->getLocale());
|
||||
JSHandle<EcmaString> localeStr =
|
||||
base::LocaleHelper::ToLanguageTag(thread, resultIculocaledisplaynames->getLocale());
|
||||
EXPECT_STREQ(EcmaStringAccessor(localeStr).ToCString().c_str(), "en");
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecmascript/base/locale_helper.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/js_array.h"
|
||||
#include "ecmascript/js_list_format.h"
|
||||
@ -275,7 +276,7 @@ std::string GetListPartStringTest(JSThread *thread, JSHandle<JSTaggedValue> key,
|
||||
JSHandle<JSObject> partObj = JSHandle<JSObject>::Cast(part);
|
||||
JSHandle<JSTaggedValue> partValue = JSObject::GetProperty(thread, partObj, key).GetValue();
|
||||
JSHandle<EcmaString> partEcmaStr = JSHandle<EcmaString>::Cast(partValue);
|
||||
std::string partStr = JSLocale::ConvertToStdString(partEcmaStr);
|
||||
std::string partStr = base::LocaleHelper::ConvertToStdString(partEcmaStr);
|
||||
return partStr;
|
||||
}
|
||||
|
||||
|
@ -141,96 +141,6 @@ HWTEST_F_L0(JSLocaleTest, GetIcuField)
|
||||
EXPECT_STREQ(result->getBaseName(), "zh_Hans_CN");
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: ConvertToStdString
|
||||
* @tc.desc: Convert char* type to std string,check whether the returned string through "ConvertToStdString"
|
||||
* function is within expectations.
|
||||
* @tc.type: FUNC
|
||||
* @tc.require:
|
||||
*/
|
||||
HWTEST_F_L0(JSLocaleTest, ConvertToStdString)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<EcmaString> handleEcmaStr = factory-> NewFromStdString("一二三四");
|
||||
std::string stdString = JSLocale::ConvertToStdString(handleEcmaStr);
|
||||
EXPECT_STREQ(stdString.c_str(), "一二三四");
|
||||
|
||||
handleEcmaStr = factory-> NewFromStdString("#%!\0@$");
|
||||
stdString = JSLocale::ConvertToStdString(handleEcmaStr);
|
||||
EXPECT_STREQ(stdString.c_str(), "#%!\0@$");
|
||||
|
||||
handleEcmaStr = factory-> NewFromStdString("123456");
|
||||
stdString = JSLocale::ConvertToStdString(handleEcmaStr);
|
||||
EXPECT_STREQ(stdString.c_str(), "123456");
|
||||
|
||||
handleEcmaStr = factory-> NewFromStdString("zhde");
|
||||
stdString = JSLocale::ConvertToStdString(handleEcmaStr);
|
||||
EXPECT_STREQ(stdString.c_str(), "zhde");
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: IsStructurallyValidLanguageTag
|
||||
* @tc.desc: Call "IsStructurallyValidLanguageTag" function check Language-Tag is valid structurally.If the tag contains
|
||||
* the correct language, region, script and extension, return true otherwise, return false.
|
||||
* @tc.type: FUNC
|
||||
* @tc.require:
|
||||
*/
|
||||
HWTEST_F_L0(JSLocaleTest, IsStructurallyValidLanguageTag)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
// number-language
|
||||
JSHandle<EcmaString> handleEcmaStr = factory->NewFromStdString("123-de");
|
||||
EXPECT_FALSE(JSLocale::IsStructurallyValidLanguageTag(handleEcmaStr));
|
||||
// only language(zh)
|
||||
handleEcmaStr = factory-> NewFromStdString("zh");
|
||||
EXPECT_TRUE(JSLocale::IsStructurallyValidLanguageTag(handleEcmaStr));
|
||||
// only language and script, region
|
||||
handleEcmaStr = factory-> NewFromStdString("zh-Hans-Cn");
|
||||
EXPECT_TRUE(JSLocale::IsStructurallyValidLanguageTag(handleEcmaStr));
|
||||
|
||||
handleEcmaStr = factory-> NewFromStdString("ja-JP-u-ca-japanese");
|
||||
EXPECT_TRUE(JSLocale::IsStructurallyValidLanguageTag(handleEcmaStr));
|
||||
|
||||
handleEcmaStr = factory-> NewFromStdString("语言脚本地区");
|
||||
EXPECT_FALSE(JSLocale::IsStructurallyValidLanguageTag(handleEcmaStr));
|
||||
|
||||
handleEcmaStr = factory-> NewFromStdString("e-US");
|
||||
EXPECT_FALSE(JSLocale::IsStructurallyValidLanguageTag(handleEcmaStr));
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: CanonicalizeUnicodeLocaleId
|
||||
* @tc.desc: Call "CanonicalizeUnicodeLocaleId" function canonicalize locale(Language-Tag),The English case of language,
|
||||
* region and script is fixed.the language is lowercase.the beginning of region is uppercase, and the script
|
||||
* is lowercase.if locale string is IsUtf16,return empty string.
|
||||
* @tc.type: FUNC
|
||||
* @tc.require:
|
||||
*/
|
||||
HWTEST_F_L0(JSLocaleTest, CanonicalizeUnicodeLocaleId)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
|
||||
JSHandle<EcmaString> locale = factory-> NewFromStdString("en-Us");
|
||||
JSHandle<EcmaString> canonicalizeLocaleId = JSLocale::CanonicalizeUnicodeLocaleId(thread, locale);
|
||||
EXPECT_STREQ("en-US", EcmaStringAccessor(canonicalizeLocaleId).ToCString().c_str());
|
||||
|
||||
locale = factory-> NewFromStdString("kO-kore-kr");
|
||||
canonicalizeLocaleId = JSLocale::CanonicalizeUnicodeLocaleId(thread, locale);
|
||||
EXPECT_STREQ("ko-Kore-KR", EcmaStringAccessor(canonicalizeLocaleId).ToCString().c_str());
|
||||
|
||||
locale = factory-> NewFromStdString("id-u-co-pinyin-de-ID");
|
||||
canonicalizeLocaleId = JSLocale::CanonicalizeUnicodeLocaleId(thread, locale);
|
||||
EXPECT_STREQ("id-u-co-pinyin-de-id", EcmaStringAccessor(canonicalizeLocaleId).ToCString().c_str());
|
||||
// invalid locale
|
||||
uint16_t localeArr[] = {0x122, 0x104, 0x45, 0x72, 0x97, 0x110, 0x115, 0x45, 0x67, 0x78}; // zh-Hans-CN
|
||||
uint32_t localeArrLength = sizeof(localeArr) / sizeof(localeArr[0]);
|
||||
locale = factory->NewFromUtf16(localeArr, localeArrLength);
|
||||
|
||||
canonicalizeLocaleId = JSLocale::CanonicalizeUnicodeLocaleId(thread, locale);
|
||||
JSHandle<EcmaString> emptyString = factory->GetEmptyString();
|
||||
EXPECT_EQ(EcmaStringAccessor::Compare(instance, canonicalizeLocaleId, emptyString), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: IsValidTimeZoneName
|
||||
* @tc.desc: Call "IsValidTimeZoneName" function check whether the TimeZone is valid.if TimeZone include "GMT-Time"
|
||||
@ -251,75 +161,6 @@ HWTEST_F_L0(JSLocaleTest, IsValidTimeZoneName)
|
||||
delete timeZone;
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: CanonicalizeLocaleList
|
||||
* @tc.desc: Create a list of locales and canonicalize the locales in the list through "CanonicalizeUnicodeLocaleId"
|
||||
* function.
|
||||
* @tc.type: FUNC
|
||||
* @tc.require:
|
||||
*/
|
||||
HWTEST_F_L0(JSLocaleTest, CanonicalizeLocaleList)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
|
||||
JSHandle<JSTaggedValue> ctor = env->GetLocaleFunction();
|
||||
JSHandle<JSLocale> jsLocale =
|
||||
JSHandle<JSLocale>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(ctor), ctor));
|
||||
// Set IcuLocale
|
||||
icu::Locale icuLocale("fr", "Latn", "Fr");
|
||||
factory->NewJSIntlIcuData(jsLocale, icuLocale, JSLocale::FreeIcuLocale);
|
||||
// test locale is jslocale
|
||||
JSHandle<TaggedArray> localeArr = JSLocale::CanonicalizeLocaleList(thread, JSHandle<JSTaggedValue>(jsLocale));
|
||||
EXPECT_EQ(localeArr->GetLength(), 1U);
|
||||
JSHandle<EcmaString> handleEcmaStr(thread, localeArr->Get(0));
|
||||
EXPECT_STREQ("fr-Latn-FR", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
|
||||
// test locale is object
|
||||
JSArray *arr = JSArray::ArrayCreate(thread, JSTaggedNumber(0)).GetObject<JSArray>();
|
||||
JSHandle<JSTaggedValue> localeObj(thread, arr);
|
||||
|
||||
JSHandle<JSTaggedValue> localeStr1(factory->NewFromASCII("EN-us"));
|
||||
PropertyDescriptor desc1(thread, localeStr1, true, true, true);
|
||||
JSHandle<JSTaggedValue> key1(factory->NewFromASCII("1"));
|
||||
JSArray::DefineOwnProperty(thread, JSHandle<JSObject>(localeObj), key1, desc1);
|
||||
|
||||
JSHandle<JSTaggedValue> localeStr2(factory->NewFromASCII("en-GB"));
|
||||
PropertyDescriptor desc2(thread, localeStr2, true, true, true);
|
||||
JSHandle<JSTaggedValue> key2(factory->NewFromASCII("2"));
|
||||
JSArray::DefineOwnProperty(thread, JSHandle<JSObject>(localeObj), key2, desc2);
|
||||
// check canonicalized string
|
||||
localeArr = JSLocale::CanonicalizeLocaleList(thread, localeObj);
|
||||
EXPECT_EQ(localeArr->GetLength(), 2U);
|
||||
JSHandle<EcmaString> resultEcmaStr1(thread, localeArr->Get(0));
|
||||
EXPECT_STREQ("en-US", EcmaStringAccessor(resultEcmaStr1).ToCString().c_str());
|
||||
JSHandle<EcmaString> resultEcmaStr2(thread, localeArr->Get(1));
|
||||
EXPECT_STREQ("en-GB", EcmaStringAccessor(resultEcmaStr2).ToCString().c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: IcuToString
|
||||
* @tc.desc: Call "IcuToString" function Convert UnicodeString to string(Utf16).
|
||||
* @tc.type: FUNC
|
||||
* @tc.require:
|
||||
*/
|
||||
HWTEST_F_L0(JSLocaleTest, IcuToString)
|
||||
{
|
||||
icu::UnicodeString unicodeString1("GMT-12:00"); // times
|
||||
JSHandle<EcmaString> ecmaString = JSLocale::IcuToString(thread, unicodeString1);
|
||||
EXPECT_STREQ("GMT-12:00", EcmaStringAccessor(ecmaString).ToCString().c_str());
|
||||
|
||||
icu::UnicodeString unicodeString2("周日16:00:00–周五23:00:00"); // date
|
||||
ecmaString = JSLocale::IcuToString(thread, unicodeString2);
|
||||
EXPECT_STREQ("周日16:00:00–周五23:00:00", EcmaStringAccessor(ecmaString).ToCString().c_str());
|
||||
|
||||
icu::UnicodeString unicodeString3("$654K"); // money
|
||||
ecmaString = JSLocale::IcuToString(thread, unicodeString3);
|
||||
EXPECT_STREQ("$654K", EcmaStringAccessor(ecmaString).ToCString().c_str());
|
||||
|
||||
icu::UnicodeString unicodeString4("1 minute ago"); // moment
|
||||
ecmaString = JSLocale::IcuToString(thread, unicodeString4, 0, 2);
|
||||
EXPECT_STREQ("1 ", EcmaStringAccessor(ecmaString).ToCString().c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: PutElement
|
||||
* @tc.desc: Put elements in empty JSArray and return the JSArray.call "GetProperty" function to get the value and
|
||||
@ -347,43 +188,6 @@ HWTEST_F_L0(JSLocaleTest, PutElement)
|
||||
EXPECT_TRUE(JSObject::GetProperty(thread, JSHandle<JSObject>(jsArray), indexKey).GetValue()->IsECMAObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: ToLanguageTag
|
||||
* @tc.desc: call "ToLanguageTag" function Convert ICU Locale into language tag.
|
||||
* @tc.type: FUNC
|
||||
* @tc.require:
|
||||
*/
|
||||
HWTEST_F_L0(JSLocaleTest, ToLanguageTag)
|
||||
{
|
||||
icu::Locale icuLocale1("en", "Latn", "US", "collation=phonebk;currency=euro");
|
||||
JSHandle<EcmaString> languageTag = JSLocale::ToLanguageTag(thread, icuLocale1);
|
||||
EXPECT_STREQ("en-Latn-US-u-co-phonebk-cu-euro", EcmaStringAccessor(languageTag).ToCString().c_str());
|
||||
|
||||
icu::Locale icuLocale2("zh", "Hans", "CN", "collation=phonebk;kn=true");
|
||||
languageTag = JSLocale::ToLanguageTag(thread, icuLocale2);
|
||||
EXPECT_STREQ("zh-Hans-CN-u-co-phonebk-kn", EcmaStringAccessor(languageTag).ToCString().c_str());
|
||||
|
||||
icu::Locale icuLocale3("ja", "Jpan", "JP", "collation=phonebk;co=yes");
|
||||
languageTag = JSLocale::ToLanguageTag(thread, icuLocale3);
|
||||
EXPECT_STREQ("ja-Jpan-JP-u-co", EcmaStringAccessor(languageTag).ToCString().c_str());
|
||||
|
||||
icu::Locale icuLocale4("z", "CN"); // language is fault
|
||||
languageTag = JSLocale::ToLanguageTag(thread, icuLocale4);
|
||||
EXPECT_STREQ("und-CN", EcmaStringAccessor(languageTag).ToCString().c_str());
|
||||
|
||||
icu::Locale icuLocale5("zh", "c"); // script is fault
|
||||
languageTag = JSLocale::ToLanguageTag(thread, icuLocale5);
|
||||
EXPECT_STREQ("zh-x-lvariant-c", EcmaStringAccessor(languageTag).ToCString().c_str());
|
||||
|
||||
icu::Locale icuLocale6("en", "Latn", "E"); // region is fault
|
||||
languageTag = JSLocale::ToLanguageTag(thread, icuLocale6);
|
||||
EXPECT_STREQ("en-Latn-x-lvariant-e", EcmaStringAccessor(languageTag).ToCString().c_str());
|
||||
|
||||
icu::Locale icuLocale7("en", "Latn", "EG", "kf=yes"); // key value is fault
|
||||
languageTag = JSLocale::ToLanguageTag(thread, icuLocale7);
|
||||
EXPECT_STREQ("en-Latn-EG-u-kf", EcmaStringAccessor(languageTag).ToCString().c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: GetNumberingSystem
|
||||
* @tc.desc: Call "GetNumberingSystem" function get the script from the ICU Locale.
|
||||
@ -445,7 +249,7 @@ HWTEST_F_L0(JSLocaleTest, ApplyOptionsToTag)
|
||||
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
|
||||
TagElements tagElements;
|
||||
JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
|
||||
JSHandle<EcmaString> languageTag = JSLocale::DefaultLocale(thread);
|
||||
JSHandle<EcmaString> languageTag = base::LocaleHelper::DefaultLocale(thread);
|
||||
|
||||
JSHandle<JSTaggedValue> languageKey = thread->GlobalConstants()->GetHandledLanguageString();
|
||||
JSHandle<JSTaggedValue> regionKey = thread->GlobalConstants()->GetHandledRegionString();
|
||||
@ -470,59 +274,6 @@ HWTEST_F_L0(JSLocaleTest, ApplyOptionsToTag)
|
||||
EXPECT_FALSE(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: HandleLocaleExtension
|
||||
* @tc.desc: Find position of subtag "x" or "u" in Locale through "HandleLocaleExtension" function.
|
||||
* @tc.type: FUNC
|
||||
* @tc.require:
|
||||
*/
|
||||
HWTEST_F_L0(JSLocaleTest, HandleLocaleExtension)
|
||||
{
|
||||
std::string result = "en-Latn-US-u-ca-gregory-co-compat";
|
||||
size_t start = 0;
|
||||
size_t extensionEnd = 0;
|
||||
JSLocale::HandleLocaleExtension(start, extensionEnd, result, result.size());
|
||||
EXPECT_EQ(extensionEnd, 10U); // the position of "u"
|
||||
// private extension("x")
|
||||
result = "de-zh-x-co-phonebk-nu-kali";
|
||||
start = 0;
|
||||
extensionEnd = 0;
|
||||
JSLocale::HandleLocaleExtension(start, extensionEnd, result, result.size());
|
||||
EXPECT_EQ(extensionEnd, 5U); // the position of "x"
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: HandleLocale
|
||||
* @tc.desc: Call "HandleLocale" function handle locale,if Locale has subtag "u" ignore it.If Locale has
|
||||
* both subtag "x" and "u","x" is in front of "u","u" does not ignore,"x" is after "u","u" ignores.
|
||||
* @tc.type: FUNC
|
||||
* @tc.require:
|
||||
*/
|
||||
HWTEST_F_L0(JSLocaleTest, HandleLocale)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
// no "u" or "x"
|
||||
JSHandle<EcmaString> localeString = factory->NewFromASCII("en-Latn-US");
|
||||
JSLocale::ParsedLocale parsedResult = JSLocale::HandleLocale(localeString);
|
||||
EXPECT_STREQ(parsedResult.base.c_str(), "en-Latn-US");
|
||||
// only "x"
|
||||
localeString = factory->NewFromASCII("zh-CN-x-ca-pinyin");
|
||||
parsedResult = JSLocale::HandleLocale(localeString);
|
||||
EXPECT_STREQ(parsedResult.base.c_str(), "zh-CN-x-ca-pinyin");
|
||||
// only "u"
|
||||
localeString = factory->NewFromASCII("ko-Kore-KR-u-co-phonebk");
|
||||
parsedResult = JSLocale::HandleLocale(localeString);
|
||||
EXPECT_STREQ(parsedResult.base.c_str(), "ko-Kore-KR");
|
||||
// both "x" and "u"
|
||||
localeString = factory->NewFromASCII("en-Latn-US-u-x-co-phonebk-kn-true");
|
||||
parsedResult = JSLocale::HandleLocale(localeString);
|
||||
EXPECT_STREQ(parsedResult.base.c_str(), "en-Latn-US-x-co-phonebk-kn-true");
|
||||
|
||||
localeString = factory->NewFromASCII("en-Latn-US-x-u-ca-pinyin-co-compat");
|
||||
parsedResult = JSLocale::HandleLocale(localeString);
|
||||
EXPECT_STREQ(parsedResult.base.c_str(), "en-Latn-US-x-u-ca-pinyin-co-compat");
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: ConstructLocaleList
|
||||
* @tc.desc: Get LocaleList numbers through "ConstructLocaleList" function.
|
||||
@ -806,43 +557,6 @@ HWTEST_F_L0(JSLocaleTest, GetOptionOfBool)
|
||||
EXPECT_FALSE(res);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: BestAvailableLocale
|
||||
* @tc.desc: Match the best Locale and return from available locale through "BestAvailableLocale" function.
|
||||
* @tc.type: FUNC
|
||||
* @tc.require:
|
||||
*/
|
||||
HWTEST_F_L0(JSLocaleTest, BestAvailableLocale)
|
||||
{
|
||||
const char *path = JSCollator::uIcuDataColl.c_str();
|
||||
// available locales in uIcuDataColl
|
||||
std::vector<std::string> icuDataAvailableLocales = JSLocale::GetAvailableLocales(thread, nullptr, path);
|
||||
// available locales(calendar)
|
||||
std::vector<std::string> calendarAvailableLocales = JSLocale::GetAvailableLocales(thread, "calendar", nullptr);
|
||||
// available locales(NumberElements)
|
||||
std::vector<std::string> numberAvailableLocales = JSLocale::GetAvailableLocales(thread, "NumberElements", nullptr);
|
||||
// "ar-001" is found
|
||||
EXPECT_STREQ(JSLocale::BestAvailableLocale(icuDataAvailableLocales, "ar-001").c_str(), "ar-001");
|
||||
EXPECT_STREQ(JSLocale::BestAvailableLocale(calendarAvailableLocales, "ar-001").c_str(), "ar-001");
|
||||
EXPECT_STREQ(JSLocale::BestAvailableLocale(numberAvailableLocales, "ar-001").c_str(), "ar-001");
|
||||
// "agq-CM" is not found in uIcuDataColl
|
||||
EXPECT_STREQ(JSLocale::BestAvailableLocale(icuDataAvailableLocales, "agq-CM").c_str(), "");
|
||||
EXPECT_STREQ(JSLocale::BestAvailableLocale(calendarAvailableLocales, "agq-CM").c_str(), "agq-CM");
|
||||
EXPECT_STREQ(JSLocale::BestAvailableLocale(numberAvailableLocales, "agq-CM").c_str(), "agq-CM");
|
||||
// language(und)-region(CN)
|
||||
EXPECT_STREQ(JSLocale::BestAvailableLocale(icuDataAvailableLocales, "und-CN").c_str(), "");
|
||||
EXPECT_STREQ(JSLocale::BestAvailableLocale(calendarAvailableLocales, "und-CN").c_str(), "");
|
||||
EXPECT_STREQ(JSLocale::BestAvailableLocale(numberAvailableLocales, "und-CN").c_str(), "");
|
||||
// language(en)-region(001)
|
||||
EXPECT_STREQ(JSLocale::BestAvailableLocale(icuDataAvailableLocales, "en-001").c_str(), "en-001");
|
||||
EXPECT_STREQ(JSLocale::BestAvailableLocale(calendarAvailableLocales, "en-001").c_str(), "en-001");
|
||||
EXPECT_STREQ(JSLocale::BestAvailableLocale(numberAvailableLocales, "en-001").c_str(), "en-001");
|
||||
// language(en)-script(Hans)-region(US)
|
||||
EXPECT_STREQ(JSLocale::BestAvailableLocale(icuDataAvailableLocales, "en-Hans-US").c_str(), "en");
|
||||
EXPECT_STREQ(JSLocale::BestAvailableLocale(calendarAvailableLocales, "en-Hans-US").c_str(), "en");
|
||||
EXPECT_STREQ(JSLocale::BestAvailableLocale(numberAvailableLocales, "en-Hans-US").c_str(), "en");
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: ResolveLocale
|
||||
* @tc.desc: Resolve Locale and return from available locale through "ResolveLocale" function.
|
||||
@ -862,7 +576,8 @@ HWTEST_F_L0(JSLocaleTest, ResolveLocale_001)
|
||||
LocaleMatcherOption::BEST_FIT, relevantExtensionKeys);
|
||||
EXPECT_STREQ("en-US", result.locale.c_str()); // default locale
|
||||
// availableLocales and requestLocales is not empty
|
||||
std::vector<std::string> availableStringLocales = JSLocale::GetAvailableLocales(thread, "calendar", nullptr);
|
||||
std::vector<std::string> availableStringLocales =
|
||||
base::LocaleHelper::GetAvailableLocales(thread, "calendar", nullptr);
|
||||
availableLocales = JSLocale::ConstructLocaleList(thread, availableStringLocales);
|
||||
requestedLocales = factory->NewTaggedArray(1);
|
||||
// test locale1
|
||||
@ -902,7 +617,8 @@ HWTEST_F_L0(JSLocaleTest, ResolveLocale_002)
|
||||
LocaleMatcherOption::BEST_FIT, relevantExtensionKeys);
|
||||
EXPECT_STREQ("en-US", result.locale.c_str()); // default locale
|
||||
// availableLocales and requestLocales is not empty
|
||||
std::vector<std::string> availableStringLocales = JSLocale::GetAvailableLocales(thread, "calendar", nullptr);
|
||||
std::vector<std::string> availableStringLocales =
|
||||
base::LocaleHelper::GetAvailableLocales(thread, "calendar", nullptr);
|
||||
availableLocales = JSLocale::ConstructLocaleList(thread, availableStringLocales);
|
||||
requestedLocales = factory->NewTaggedArray(1);
|
||||
// test locale1
|
||||
|
@ -13,6 +13,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecmascript/base/locale_helper.h"
|
||||
#include "ecmascript/js_number_format.h"
|
||||
#include "ecmascript/napi/jsnapi_helper.h"
|
||||
#include "ecmascript/tests/test_helper.h"
|
||||
@ -86,7 +87,7 @@ HWTEST_F_L0(JSNumberFormatTest, GetIcuCallTarget)
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
icu::number::FormattedNumber formattedNumber = resultIcuNumberFormatter->formatInt(value, status);
|
||||
icu::UnicodeString result = formattedNumber.toString(status);
|
||||
JSHandle<EcmaString> stringValue = JSLocale::IcuToString(thread, result);
|
||||
JSHandle<EcmaString> stringValue = base::LocaleHelper::UStringToString(thread, result);
|
||||
EXPECT_STREQ("-123,456", EcmaStringAccessor(stringValue).ToCString().c_str());
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecmascript/base/locale_helper.h"
|
||||
#include "ecmascript/js_plural_rules.h"
|
||||
#include "ecmascript/base/number_helper.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
@ -73,12 +74,12 @@ HWTEST_F_L0(JSPluralRulesTest, GetIcuPluralRules)
|
||||
UPluralType icuType = UPLURAL_TYPE_CARDINAL; // Plural rules for cardinal numbers
|
||||
icu::PluralRules *icuPluralRules(icu::PluralRules::forLocale(icuLocale, icuType, status));
|
||||
icu::UnicodeString result1 = icuPluralRules->select(0);
|
||||
JSHandle<EcmaString> stringValue1 = JSLocale::IcuToString(thread, result1);
|
||||
JSHandle<EcmaString> stringValue1 = base::LocaleHelper::UStringToString(thread, result1);
|
||||
|
||||
JSPluralRules::SetIcuPluralRules(thread, pluralRules, *icuPluralRules, JSPluralRules::FreeIcuPluralRules);
|
||||
icu::PluralRules *getPluralRules = pluralRules->GetIcuPluralRules();
|
||||
icu::UnicodeString result2 = getPluralRules->select(0);
|
||||
JSHandle<EcmaString> stringValue2 = JSLocale::IcuToString(thread, result2);
|
||||
JSHandle<EcmaString> stringValue2 = base::LocaleHelper::UStringToString(thread, result2);
|
||||
EXPECT_EQ(EcmaStringAccessor::StringsAreEqual(*stringValue1, *stringValue2), true);
|
||||
delete icuPluralRules;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "ecmascript/js_relative_time_format.h"
|
||||
#include "ecmascript/base/locale_helper.h"
|
||||
#include "ecmascript/base/number_helper.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/napi/jsnapi_helper.h"
|
||||
@ -98,14 +99,14 @@ HWTEST_F_L0(JSRelativeTimeFormatTest, GetIcuRTFFormatter)
|
||||
icu::RelativeDateTimeFormatter rtfFormatter(icuLocale, icuNumberFormat, UDAT_STYLE_LONG,
|
||||
UDISPCTX_CAPITALIZATION_NONE, status);
|
||||
icu::UnicodeString result1 = rtfFormatter.formatNumericToValue(value, UDAT_REL_UNIT_YEAR, status).toString(status);
|
||||
JSHandle<EcmaString> stringValue1 = JSLocale::IcuToString(thread, result1);
|
||||
JSHandle<EcmaString> stringValue1 = base::LocaleHelper::UStringToString(thread, result1);
|
||||
// Set Icu RelativeDateTimeFormatter to Icu Field
|
||||
factory->NewJSIntlIcuData(relativeTimeFormat, rtfFormatter, JSRelativeTimeFormat::FreeIcuRTFFormatter);
|
||||
// Get Icu Field
|
||||
icu::RelativeDateTimeFormatter *resultRelativeDateTimeFormatter = relativeTimeFormat->GetIcuRTFFormatter();
|
||||
icu::UnicodeString result2 =
|
||||
resultRelativeDateTimeFormatter->formatNumericToValue(value, UDAT_REL_UNIT_YEAR, status).toString(status);
|
||||
JSHandle<EcmaString> stringValue2 = JSLocale::IcuToString(thread, result2);
|
||||
JSHandle<EcmaString> stringValue2 = base::LocaleHelper::UStringToString(thread, result2);
|
||||
EXPECT_EQ(EcmaStringAccessor::StringsAreEqual(*stringValue1, *stringValue2), true);
|
||||
}
|
||||
|
||||
|
351
ecmascript/tests/locale_helper_test.cpp
Normal file
351
ecmascript/tests/locale_helper_test.cpp
Normal file
@ -0,0 +1,351 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecmascript/base/locale_helper.h"
|
||||
#include "ecmascript/ecma_string.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/js_collator.h"
|
||||
#include "ecmascript/tests/test_helper.h"
|
||||
|
||||
using namespace panda::ecmascript;
|
||||
using namespace panda::ecmascript::base;
|
||||
|
||||
namespace panda::test {
|
||||
class LocaleHelperTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase()
|
||||
{
|
||||
GTEST_LOG_(INFO) << "SetUpTestCase";
|
||||
}
|
||||
|
||||
static void TearDownTestCase()
|
||||
{
|
||||
GTEST_LOG_(INFO) << "TearDownCase";
|
||||
}
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
JSRuntimeOptions options;
|
||||
#if PANDA_TARGET_LINUX
|
||||
// for consistency requirement, use ohos_icu4j/data as icu-data-path
|
||||
options.SetIcuDataPath(ICU_PATH);
|
||||
#endif
|
||||
options.SetEnableForceGC(true);
|
||||
instance = JSNApi::CreateEcmaVM(options);
|
||||
instance->SetEnableForceGC(true);
|
||||
ASSERT_TRUE(instance != nullptr) << "Cannot create EcmaVM";
|
||||
thread = instance->GetJSThread();
|
||||
scope = new EcmaHandleScope(thread);
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
TestHelper::DestroyEcmaVMWithScope(instance, scope);
|
||||
}
|
||||
|
||||
EcmaVM *instance {nullptr};
|
||||
ecmascript::EcmaHandleScope *scope {nullptr};
|
||||
JSThread *thread {nullptr};
|
||||
};
|
||||
|
||||
/**
|
||||
* @tc.name: UStringToString
|
||||
* @tc.desc: Call "UStringToString" function Convert UnicodeString to string(Utf16).
|
||||
* @tc.type: FUNC
|
||||
* @tc.require:
|
||||
*/
|
||||
HWTEST_F_L0(LocaleHelperTest, UStringToString)
|
||||
{
|
||||
icu::UnicodeString unicodeString1("GMT-12:00"); // times
|
||||
JSHandle<EcmaString> ecmaString = LocaleHelper::UStringToString(thread, unicodeString1);
|
||||
EXPECT_STREQ("GMT-12:00", EcmaStringAccessor(ecmaString).ToCString().c_str());
|
||||
|
||||
icu::UnicodeString unicodeString2("周日16:00:00–周五23:00:00"); // date
|
||||
ecmaString = LocaleHelper::UStringToString(thread, unicodeString2);
|
||||
EXPECT_STREQ("周日16:00:00–周五23:00:00", EcmaStringAccessor(ecmaString).ToCString().c_str());
|
||||
|
||||
icu::UnicodeString unicodeString3("$654K"); // money
|
||||
ecmaString = LocaleHelper::UStringToString(thread, unicodeString3);
|
||||
EXPECT_STREQ("$654K", EcmaStringAccessor(ecmaString).ToCString().c_str());
|
||||
|
||||
icu::UnicodeString unicodeString4("1 minute ago"); // moment
|
||||
ecmaString = LocaleHelper::UStringToString(thread, unicodeString4, 0, 2);
|
||||
EXPECT_STREQ("1 ", EcmaStringAccessor(ecmaString).ToCString().c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: CanonicalizeLocaleList
|
||||
* @tc.desc: Create a list of locales and canonicalize the locales in the list through "CanonicalizeUnicodeLocaleId"
|
||||
* function.
|
||||
* @tc.type: FUNC
|
||||
* @tc.require:
|
||||
*/
|
||||
HWTEST_F_L0(LocaleHelperTest, CanonicalizeLocaleList)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
|
||||
JSHandle<JSTaggedValue> ctor = env->GetLocaleFunction();
|
||||
JSHandle<JSLocale> jsLocale =
|
||||
JSHandle<JSLocale>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(ctor), ctor));
|
||||
// Set IcuLocale
|
||||
icu::Locale icuLocale("fr", "Latn", "Fr");
|
||||
factory->NewJSIntlIcuData(jsLocale, icuLocale, JSLocale::FreeIcuLocale);
|
||||
// test locale is jslocale
|
||||
JSHandle<TaggedArray> localeArr = LocaleHelper::CanonicalizeLocaleList(thread, JSHandle<JSTaggedValue>(jsLocale));
|
||||
EXPECT_EQ(localeArr->GetLength(), 1U);
|
||||
JSHandle<EcmaString> handleEcmaStr(thread, localeArr->Get(0));
|
||||
EXPECT_STREQ("fr-Latn-FR", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
|
||||
// test locale is object
|
||||
JSArray *arr = JSArray::ArrayCreate(thread, JSTaggedNumber(0)).GetObject<JSArray>();
|
||||
JSHandle<JSTaggedValue> localeObj(thread, arr);
|
||||
|
||||
JSHandle<JSTaggedValue> localeStr1(factory->NewFromASCII("EN-us"));
|
||||
PropertyDescriptor desc1(thread, localeStr1, true, true, true);
|
||||
JSHandle<JSTaggedValue> key1(factory->NewFromASCII("1"));
|
||||
JSArray::DefineOwnProperty(thread, JSHandle<JSObject>(localeObj), key1, desc1);
|
||||
|
||||
JSHandle<JSTaggedValue> localeStr2(factory->NewFromASCII("en-GB"));
|
||||
PropertyDescriptor desc2(thread, localeStr2, true, true, true);
|
||||
JSHandle<JSTaggedValue> key2(factory->NewFromASCII("2"));
|
||||
JSArray::DefineOwnProperty(thread, JSHandle<JSObject>(localeObj), key2, desc2);
|
||||
// check canonicalized string
|
||||
localeArr = LocaleHelper::CanonicalizeLocaleList(thread, localeObj);
|
||||
EXPECT_EQ(localeArr->GetLength(), 2U);
|
||||
JSHandle<EcmaString> resultEcmaStr1(thread, localeArr->Get(0));
|
||||
EXPECT_STREQ("en-US", EcmaStringAccessor(resultEcmaStr1).ToCString().c_str());
|
||||
JSHandle<EcmaString> resultEcmaStr2(thread, localeArr->Get(1));
|
||||
EXPECT_STREQ("en-GB", EcmaStringAccessor(resultEcmaStr2).ToCString().c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: CanonicalizeUnicodeLocaleId
|
||||
* @tc.desc: Call "CanonicalizeUnicodeLocaleId" function canonicalize locale(Language-Tag),The English case of language,
|
||||
* region and script is fixed.the language is lowercase.the beginning of region is uppercase, and the script
|
||||
* is lowercase.if locale string is IsUtf16,return empty string.
|
||||
* @tc.type: FUNC
|
||||
* @tc.require:
|
||||
*/
|
||||
HWTEST_F_L0(LocaleHelperTest, CanonicalizeUnicodeLocaleId)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
|
||||
JSHandle<EcmaString> locale = factory-> NewFromStdString("en-Us");
|
||||
JSHandle<EcmaString> canonicalizeLocaleId = LocaleHelper::CanonicalizeUnicodeLocaleId(thread, locale);
|
||||
EXPECT_STREQ("en-US", EcmaStringAccessor(canonicalizeLocaleId).ToCString().c_str());
|
||||
|
||||
locale = factory-> NewFromStdString("kO-kore-kr");
|
||||
canonicalizeLocaleId = LocaleHelper::CanonicalizeUnicodeLocaleId(thread, locale);
|
||||
EXPECT_STREQ("ko-Kore-KR", EcmaStringAccessor(canonicalizeLocaleId).ToCString().c_str());
|
||||
|
||||
locale = factory-> NewFromStdString("id-u-co-pinyin-de-ID");
|
||||
canonicalizeLocaleId = LocaleHelper::CanonicalizeUnicodeLocaleId(thread, locale);
|
||||
EXPECT_STREQ("id-u-co-pinyin-de-id", EcmaStringAccessor(canonicalizeLocaleId).ToCString().c_str());
|
||||
// invalid locale
|
||||
uint16_t localeArr[] = {0x122, 0x104, 0x45, 0x72, 0x97, 0x110, 0x115, 0x45, 0x67, 0x78}; // zh-Hans-CN
|
||||
uint32_t localeArrLength = sizeof(localeArr) / sizeof(localeArr[0]);
|
||||
locale = factory->NewFromUtf16(localeArr, localeArrLength);
|
||||
|
||||
canonicalizeLocaleId = LocaleHelper::CanonicalizeUnicodeLocaleId(thread, locale);
|
||||
JSHandle<EcmaString> emptyString = factory->GetEmptyString();
|
||||
EXPECT_EQ(EcmaStringAccessor::Compare(instance, canonicalizeLocaleId, emptyString), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: ToLanguageTag
|
||||
* @tc.desc: call "ToLanguageTag" function Convert ICU Locale into language tag.
|
||||
* @tc.type: FUNC
|
||||
* @tc.require:
|
||||
*/
|
||||
HWTEST_F_L0(LocaleHelperTest, ToLanguageTag)
|
||||
{
|
||||
icu::Locale icuLocale1("en", "Latn", "US", "collation=phonebk;currency=euro");
|
||||
JSHandle<EcmaString> languageTag = LocaleHelper::ToLanguageTag(thread, icuLocale1);
|
||||
EXPECT_STREQ("en-Latn-US-u-co-phonebk-cu-euro", EcmaStringAccessor(languageTag).ToCString().c_str());
|
||||
|
||||
icu::Locale icuLocale2("zh", "Hans", "CN", "collation=phonebk;kn=true");
|
||||
languageTag = LocaleHelper::ToLanguageTag(thread, icuLocale2);
|
||||
EXPECT_STREQ("zh-Hans-CN-u-co-phonebk-kn", EcmaStringAccessor(languageTag).ToCString().c_str());
|
||||
|
||||
icu::Locale icuLocale3("ja", "Jpan", "JP", "collation=phonebk;co=yes");
|
||||
languageTag = LocaleHelper::ToLanguageTag(thread, icuLocale3);
|
||||
EXPECT_STREQ("ja-Jpan-JP-u-co", EcmaStringAccessor(languageTag).ToCString().c_str());
|
||||
|
||||
icu::Locale icuLocale4("z", "CN"); // language is fault
|
||||
languageTag = LocaleHelper::ToLanguageTag(thread, icuLocale4);
|
||||
EXPECT_STREQ("und-CN", EcmaStringAccessor(languageTag).ToCString().c_str());
|
||||
|
||||
icu::Locale icuLocale5("zh", "c"); // script is fault
|
||||
languageTag = LocaleHelper::ToLanguageTag(thread, icuLocale5);
|
||||
EXPECT_STREQ("zh-x-lvariant-c", EcmaStringAccessor(languageTag).ToCString().c_str());
|
||||
|
||||
icu::Locale icuLocale6("en", "Latn", "E"); // region is fault
|
||||
languageTag = LocaleHelper::ToLanguageTag(thread, icuLocale6);
|
||||
EXPECT_STREQ("en-Latn-x-lvariant-e", EcmaStringAccessor(languageTag).ToCString().c_str());
|
||||
|
||||
icu::Locale icuLocale7("en", "Latn", "EG", "kf=yes"); // key value is fault
|
||||
languageTag = LocaleHelper::ToLanguageTag(thread, icuLocale7);
|
||||
EXPECT_STREQ("en-Latn-EG-u-kf", EcmaStringAccessor(languageTag).ToCString().c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: IsStructurallyValidLanguageTag
|
||||
* @tc.desc: Call "IsStructurallyValidLanguageTag" function check Language-Tag is valid structurally.If the tag contains
|
||||
* the correct language, region, script and extension, return true otherwise, return false.
|
||||
* @tc.type: FUNC
|
||||
* @tc.require:
|
||||
*/
|
||||
HWTEST_F_L0(LocaleHelperTest, IsStructurallyValidLanguageTag)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
// number-language
|
||||
JSHandle<EcmaString> handleEcmaStr = factory->NewFromStdString("123-de");
|
||||
EXPECT_FALSE(LocaleHelper::IsStructurallyValidLanguageTag(handleEcmaStr));
|
||||
// only language(zh)
|
||||
handleEcmaStr = factory-> NewFromStdString("zh");
|
||||
EXPECT_TRUE(LocaleHelper::IsStructurallyValidLanguageTag(handleEcmaStr));
|
||||
// only language and script, region
|
||||
handleEcmaStr = factory-> NewFromStdString("zh-Hans-Cn");
|
||||
EXPECT_TRUE(LocaleHelper::IsStructurallyValidLanguageTag(handleEcmaStr));
|
||||
|
||||
handleEcmaStr = factory-> NewFromStdString("ja-JP-u-ca-japanese");
|
||||
EXPECT_TRUE(LocaleHelper::IsStructurallyValidLanguageTag(handleEcmaStr));
|
||||
|
||||
handleEcmaStr = factory-> NewFromStdString("语言脚本地区");
|
||||
EXPECT_FALSE(LocaleHelper::IsStructurallyValidLanguageTag(handleEcmaStr));
|
||||
|
||||
handleEcmaStr = factory-> NewFromStdString("e-US");
|
||||
EXPECT_FALSE(LocaleHelper::IsStructurallyValidLanguageTag(handleEcmaStr));
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: ConvertToStdString
|
||||
* @tc.desc: Convert char* type to std string,check whether the returned string through "ConvertToStdString"
|
||||
* function is within expectations.
|
||||
* @tc.type: FUNC
|
||||
* @tc.require:
|
||||
*/
|
||||
HWTEST_F_L0(LocaleHelperTest, ConvertToStdString)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<EcmaString> handleEcmaStr = factory-> NewFromStdString("一二三四");
|
||||
std::string stdString = LocaleHelper::ConvertToStdString(handleEcmaStr);
|
||||
EXPECT_STREQ(stdString.c_str(), "一二三四");
|
||||
|
||||
handleEcmaStr = factory-> NewFromStdString("#%!\0@$");
|
||||
stdString = LocaleHelper::ConvertToStdString(handleEcmaStr);
|
||||
EXPECT_STREQ(stdString.c_str(), "#%!\0@$");
|
||||
|
||||
handleEcmaStr = factory-> NewFromStdString("123456");
|
||||
stdString = LocaleHelper::ConvertToStdString(handleEcmaStr);
|
||||
EXPECT_STREQ(stdString.c_str(), "123456");
|
||||
|
||||
handleEcmaStr = factory-> NewFromStdString("zhde");
|
||||
stdString = LocaleHelper::ConvertToStdString(handleEcmaStr);
|
||||
EXPECT_STREQ(stdString.c_str(), "zhde");
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: HandleLocaleExtension
|
||||
* @tc.desc: Find position of subtag "x" or "u" in Locale through "HandleLocaleExtension" function.
|
||||
* @tc.type: FUNC
|
||||
* @tc.require:
|
||||
*/
|
||||
HWTEST_F_L0(LocaleHelperTest, HandleLocaleExtension)
|
||||
{
|
||||
std::string result = "en-Latn-US-u-ca-gregory-co-compat";
|
||||
size_t start = 0;
|
||||
size_t extensionEnd = 0;
|
||||
LocaleHelper::HandleLocaleExtension(start, extensionEnd, result, result.size());
|
||||
EXPECT_EQ(extensionEnd, 10U); // the position of "u"
|
||||
// private extension("x")
|
||||
result = "de-zh-x-co-phonebk-nu-kali";
|
||||
start = 0;
|
||||
extensionEnd = 0;
|
||||
LocaleHelper::HandleLocaleExtension(start, extensionEnd, result, result.size());
|
||||
EXPECT_EQ(extensionEnd, 5U); // the position of "x"
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: HandleLocale
|
||||
* @tc.desc: Call "HandleLocale" function handle locale,if Locale has subtag "u" ignore it.If Locale has
|
||||
* both subtag "x" and "u","x" is in front of "u","u" does not ignore,"x" is after "u","u" ignores.
|
||||
* @tc.type: FUNC
|
||||
* @tc.require:
|
||||
*/
|
||||
HWTEST_F_L0(LocaleHelperTest, HandleLocale)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
// no "u" or "x"
|
||||
JSHandle<EcmaString> localeString = factory->NewFromASCII("en-Latn-US");
|
||||
LocaleHelper::ParsedLocale parsedResult = LocaleHelper::HandleLocale(localeString);
|
||||
EXPECT_STREQ(parsedResult.base.c_str(), "en-Latn-US");
|
||||
// only "x"
|
||||
localeString = factory->NewFromASCII("zh-CN-x-ca-pinyin");
|
||||
parsedResult = LocaleHelper::HandleLocale(localeString);
|
||||
EXPECT_STREQ(parsedResult.base.c_str(), "zh-CN-x-ca-pinyin");
|
||||
// only "u"
|
||||
localeString = factory->NewFromASCII("ko-Kore-KR-u-co-phonebk");
|
||||
parsedResult = LocaleHelper::HandleLocale(localeString);
|
||||
EXPECT_STREQ(parsedResult.base.c_str(), "ko-Kore-KR");
|
||||
// both "x" and "u"
|
||||
localeString = factory->NewFromASCII("en-Latn-US-u-x-co-phonebk-kn-true");
|
||||
parsedResult = LocaleHelper::HandleLocale(localeString);
|
||||
EXPECT_STREQ(parsedResult.base.c_str(), "en-Latn-US-x-co-phonebk-kn-true");
|
||||
|
||||
localeString = factory->NewFromASCII("en-Latn-US-x-u-ca-pinyin-co-compat");
|
||||
parsedResult = LocaleHelper::HandleLocale(localeString);
|
||||
EXPECT_STREQ(parsedResult.base.c_str(), "en-Latn-US-x-u-ca-pinyin-co-compat");
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: BestAvailableLocale
|
||||
* @tc.desc: Match the best Locale and return from available locale through "BestAvailableLocale" function.
|
||||
* @tc.type: FUNC
|
||||
* @tc.require:
|
||||
*/
|
||||
HWTEST_F_L0(LocaleHelperTest, BestAvailableLocale)
|
||||
{
|
||||
const char *path = JSCollator::uIcuDataColl.c_str();
|
||||
// available locales in uIcuDataColl
|
||||
std::vector<std::string> icuDataAvailableLocales =
|
||||
LocaleHelper::GetAvailableLocales(thread, nullptr, path);
|
||||
// available locales(calendar)
|
||||
std::vector<std::string> calendarAvailableLocales =
|
||||
LocaleHelper::GetAvailableLocales(thread, "calendar", nullptr);
|
||||
// available locales(NumberElements)
|
||||
std::vector<std::string> numberAvailableLocales =
|
||||
LocaleHelper::GetAvailableLocales(thread, "NumberElements", nullptr);
|
||||
// "ar-001" is found
|
||||
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(icuDataAvailableLocales, "ar-001").c_str(), "ar-001");
|
||||
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(calendarAvailableLocales, "ar-001").c_str(), "ar-001");
|
||||
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(numberAvailableLocales, "ar-001").c_str(), "ar-001");
|
||||
// "agq-CM" is not found in uIcuDataColl
|
||||
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(icuDataAvailableLocales, "agq-CM").c_str(), "");
|
||||
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(calendarAvailableLocales, "agq-CM").c_str(), "agq-CM");
|
||||
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(numberAvailableLocales, "agq-CM").c_str(), "agq-CM");
|
||||
// language(und)-region(CN)
|
||||
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(icuDataAvailableLocales, "und-CN").c_str(), "");
|
||||
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(calendarAvailableLocales, "und-CN").c_str(), "");
|
||||
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(numberAvailableLocales, "und-CN").c_str(), "");
|
||||
// language(en)-region(001)
|
||||
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(icuDataAvailableLocales, "en-001").c_str(), "en-001");
|
||||
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(calendarAvailableLocales, "en-001").c_str(), "en-001");
|
||||
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(numberAvailableLocales, "en-001").c_str(), "en-001");
|
||||
// language(en)-script(Hans)-region(US)
|
||||
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(icuDataAvailableLocales, "en-Hans-US").c_str(), "en");
|
||||
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(calendarAvailableLocales, "en-Hans-US").c_str(), "en");
|
||||
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(numberAvailableLocales, "en-Hans-US").c_str(), "en");
|
||||
}
|
||||
} // namespace panda::test
|
Loading…
Reference in New Issue
Block a user