mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Bug 1426907
- Update OSPreferences API to use UTF-8 rather than UTF-16; r=zbraniecki
We'll want to use UTF-8 when we switch to using ICU4x because Rust is all UTF-8. We can switch the external facing APIs now, and update the internal implementations later. Differential Revision: https://phabricator.services.mozilla.com/D94850
This commit is contained in:
parent
3790450033
commit
686b723d0d
@ -73,7 +73,7 @@ nsresult DateTimeFormat::FormatDateTime(
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
nsAutoString skeleton;
|
||||
nsAutoCString skeleton;
|
||||
switch (aSkeleton) {
|
||||
case Skeleton::yyyyMM:
|
||||
skeleton.AssignASCII("yyyyMM");
|
||||
@ -85,10 +85,11 @@ nsresult DateTimeFormat::FormatDateTime(
|
||||
MOZ_ASSERT_UNREACHABLE("Unhandled skeleton enum");
|
||||
}
|
||||
|
||||
nsAutoString pattern;
|
||||
if (!OSPreferences::GetPatternForSkeleton(skeleton, *mLocale, pattern)) {
|
||||
nsAutoCString str;
|
||||
if (!OSPreferences::GetPatternForSkeleton(skeleton, *mLocale, str)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsAutoString pattern = NS_ConvertUTF8toUTF16(str);
|
||||
|
||||
nsAutoString timeZoneID;
|
||||
BuildTimeZoneString(aExplodedTime->tm_params, timeZoneID);
|
||||
@ -253,7 +254,6 @@ nsresult DateTimeFormat::FormatUDateTime(
|
||||
if (!dateTimeFormat) {
|
||||
// We didn't have a cached formatter for this key, so create one.
|
||||
|
||||
nsAutoString pattern;
|
||||
int32_t dateFormatStyle;
|
||||
switch (aDateFormatSelector) {
|
||||
case kDateFormatLong:
|
||||
@ -286,10 +286,12 @@ nsresult DateTimeFormat::FormatUDateTime(
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
nsAutoCString str;
|
||||
rv = OSPreferences::GetInstance()->GetDateTimePattern(
|
||||
dateFormatStyle, timeFormatStyle, nsDependentCString(mLocale->get()),
|
||||
pattern);
|
||||
str);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsAutoString pattern = NS_ConvertUTF8toUTF16(str);
|
||||
|
||||
if (aTimeParameters) {
|
||||
nsAutoString timeZoneID;
|
||||
|
@ -63,7 +63,7 @@ bool OSPreferences::CanonicalizeLanguageTag(nsCString& aLoc) {
|
||||
bool OSPreferences::GetDateTimePatternForStyle(DateTimeFormatStyle aDateStyle,
|
||||
DateTimeFormatStyle aTimeStyle,
|
||||
const nsACString& aLocale,
|
||||
nsAString& aRetVal) {
|
||||
nsACString& aRetVal) {
|
||||
UDateFormatStyle timeStyle = UDAT_NONE;
|
||||
UDateFormatStyle dateStyle = UDAT_NONE;
|
||||
|
||||
@ -133,7 +133,7 @@ bool OSPreferences::GetDateTimePatternForStyle(DateTimeFormatStyle aDateStyle,
|
||||
if (U_FAILURE(status)) {
|
||||
return false;
|
||||
}
|
||||
aRetVal.Assign((const char16_t*)pattern, patsize);
|
||||
aRetVal = NS_ConvertUTF16toUTF8(pattern, patsize);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -148,24 +148,26 @@ bool OSPreferences::GetDateTimePatternForStyle(DateTimeFormatStyle aDateStyle,
|
||||
bool OSPreferences::GetDateTimeSkeletonForStyle(DateTimeFormatStyle aDateStyle,
|
||||
DateTimeFormatStyle aTimeStyle,
|
||||
const nsACString& aLocale,
|
||||
nsAString& aRetVal) {
|
||||
nsAutoString pattern;
|
||||
nsACString& aRetVal) {
|
||||
nsAutoCString pattern;
|
||||
if (!GetDateTimePatternForStyle(aDateStyle, aTimeStyle, aLocale, pattern)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoString patternAsUtf16 = NS_ConvertUTF8toUTF16(pattern);
|
||||
|
||||
const int32_t kSkeletonMax = 160;
|
||||
UChar skeleton[kSkeletonMax];
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
int32_t skelsize =
|
||||
udatpg_getSkeleton(nullptr, (const UChar*)pattern.BeginReading(),
|
||||
pattern.Length(), skeleton, kSkeletonMax, &status);
|
||||
int32_t skelsize = udatpg_getSkeleton(
|
||||
nullptr, (const UChar*)patternAsUtf16.BeginReading(),
|
||||
patternAsUtf16.Length(), skeleton, kSkeletonMax, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aRetVal.Assign((const char16_t*)skeleton, skelsize);
|
||||
aRetVal = NS_ConvertUTF16toUTF8(skeleton, skelsize);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -178,9 +180,11 @@ bool OSPreferences::GetDateTimeSkeletonForStyle(DateTimeFormatStyle aDateStyle,
|
||||
* For example:
|
||||
* "Hm" skeleton for "en-US" will return "H:m"
|
||||
*/
|
||||
bool OSPreferences::GetPatternForSkeleton(const nsAString& aSkeleton,
|
||||
bool OSPreferences::GetPatternForSkeleton(const nsACString& aSkeleton,
|
||||
const nsACString& aLocale,
|
||||
nsAString& aRetVal) {
|
||||
nsACString& aRetVal) {
|
||||
aRetVal.Truncate();
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UDateTimePatternGenerator* pg =
|
||||
udatpg_open(PromiseFlatCString(aLocale).get(), &status);
|
||||
@ -188,19 +192,26 @@ bool OSPreferences::GetPatternForSkeleton(const nsAString& aSkeleton,
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoString skeletonAsUtf16 = NS_ConvertUTF8toUTF16(aSkeleton);
|
||||
nsAutoString result;
|
||||
|
||||
int32_t len =
|
||||
udatpg_getBestPattern(pg, (const UChar*)aSkeleton.BeginReading(),
|
||||
aSkeleton.Length(), nullptr, 0, &status);
|
||||
udatpg_getBestPattern(pg, (const UChar*)skeletonAsUtf16.BeginReading(),
|
||||
skeletonAsUtf16.Length(), nullptr, 0, &status);
|
||||
if (status == U_BUFFER_OVERFLOW_ERROR) { // expected
|
||||
aRetVal.SetLength(len);
|
||||
result.SetLength(len);
|
||||
status = U_ZERO_ERROR;
|
||||
udatpg_getBestPattern(pg, (const UChar*)aSkeleton.BeginReading(),
|
||||
aSkeleton.Length(), (UChar*)aRetVal.BeginWriting(),
|
||||
len, &status);
|
||||
udatpg_getBestPattern(pg, (const UChar*)skeletonAsUtf16.BeginReading(),
|
||||
skeletonAsUtf16.Length(),
|
||||
(UChar*)result.BeginWriting(), len, &status);
|
||||
}
|
||||
|
||||
udatpg_close(pg);
|
||||
|
||||
if (U_SUCCESS(status)) {
|
||||
aRetVal = NS_ConvertUTF16toUTF8(result);
|
||||
}
|
||||
|
||||
return U_SUCCESS(status);
|
||||
}
|
||||
|
||||
@ -214,7 +225,7 @@ bool OSPreferences::GetPatternForSkeleton(const nsAString& aSkeleton,
|
||||
* An example output is "{1}, {0}".
|
||||
*/
|
||||
bool OSPreferences::GetDateTimeConnectorPattern(const nsACString& aLocale,
|
||||
nsAString& aRetVal) {
|
||||
nsACString& aRetVal) {
|
||||
bool result = false;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UDateTimePatternGenerator* pg =
|
||||
@ -224,7 +235,7 @@ bool OSPreferences::GetDateTimeConnectorPattern(const nsACString& aLocale,
|
||||
const UChar* value = udatpg_getDateTimeFormat(pg, &resultSize);
|
||||
MOZ_ASSERT(resultSize >= 0);
|
||||
|
||||
aRetVal.Assign((char16_t*)value, resultSize);
|
||||
aRetVal = NS_ConvertUTF16toUTF8(value, resultSize);
|
||||
result = true;
|
||||
}
|
||||
udatpg_close(pg);
|
||||
@ -306,7 +317,7 @@ NS_IMETHODIMP
|
||||
OSPreferences::GetDateTimePattern(int32_t aDateFormatStyle,
|
||||
int32_t aTimeFormatStyle,
|
||||
const nsACString& aLocale,
|
||||
nsAString& aRetVal) {
|
||||
nsACString& aRetVal) {
|
||||
DateTimeFormatStyle dateStyle = ToDateTimeFormatStyle(aDateFormatStyle);
|
||||
if (dateStyle == DateTimeFormatStyle::Invalid) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
@ -330,7 +341,7 @@ OSPreferences::GetDateTimePattern(int32_t aDateFormatStyle,
|
||||
key.Append(':');
|
||||
key.AppendInt(aTimeFormatStyle);
|
||||
|
||||
nsString pattern;
|
||||
nsCString pattern;
|
||||
if (mPatternCache.Get(key, &pattern)) {
|
||||
aRetVal = pattern;
|
||||
return NS_OK;
|
||||
|
@ -77,12 +77,12 @@ class OSPreferences : public mozIOSPreferences {
|
||||
return RefPtr<OSPreferences>(GetInstance()).forget();
|
||||
}
|
||||
|
||||
static bool GetPatternForSkeleton(const nsAString& aSkeleton,
|
||||
static bool GetPatternForSkeleton(const nsACString& aSkeleton,
|
||||
const nsACString& aLocale,
|
||||
nsAString& aRetVal);
|
||||
nsACString& aRetVal);
|
||||
|
||||
static bool GetDateTimeConnectorPattern(const nsACString& aLocale,
|
||||
nsAString& aRetVal);
|
||||
nsACString& aRetVal);
|
||||
|
||||
/**
|
||||
* Triggers a refresh of retrieving data from host environment.
|
||||
@ -102,7 +102,7 @@ class OSPreferences : public mozIOSPreferences {
|
||||
nsTArray<nsCString> mRegionalPrefsLocales;
|
||||
|
||||
const size_t kMaxCachedPatterns = 15;
|
||||
nsDataHashtable<nsCStringHashKey, nsString> mPatternCache;
|
||||
nsDataHashtable<nsCStringHashKey, nsCString> mPatternCache;
|
||||
|
||||
private:
|
||||
virtual ~OSPreferences();
|
||||
@ -118,12 +118,12 @@ class OSPreferences : public mozIOSPreferences {
|
||||
bool GetDateTimePatternForStyle(DateTimeFormatStyle aDateStyle,
|
||||
DateTimeFormatStyle aTimeStyle,
|
||||
const nsACString& aLocale,
|
||||
nsAString& aRetVal);
|
||||
nsACString& aRetVal);
|
||||
|
||||
bool GetDateTimeSkeletonForStyle(DateTimeFormatStyle aDateStyle,
|
||||
DateTimeFormatStyle aTimeStyle,
|
||||
const nsACString& aLocale,
|
||||
nsAString& aRetVal);
|
||||
nsACString& aRetVal);
|
||||
|
||||
/**
|
||||
* This is a host environment specific method that will be implemented
|
||||
@ -153,7 +153,7 @@ class OSPreferences : public mozIOSPreferences {
|
||||
*/
|
||||
bool ReadDateTimePattern(DateTimeFormatStyle aDateFormatStyle,
|
||||
DateTimeFormatStyle aTimeFormatStyle,
|
||||
const nsACString& aLocale, nsAString& aRetVal);
|
||||
const nsACString& aLocale, nsACString& aRetVal);
|
||||
};
|
||||
|
||||
} // namespace intl
|
||||
|
@ -43,6 +43,6 @@ bool OSPreferences::ReadRegionalPrefsLocales(nsTArray<nsCString>& aLocaleList) {
|
||||
bool OSPreferences::ReadDateTimePattern(DateTimeFormatStyle aDateStyle,
|
||||
DateTimeFormatStyle aTimeStyle,
|
||||
const nsACString& aLocale,
|
||||
nsAString& aRetVal) {
|
||||
nsACString& aRetVal) {
|
||||
return false;
|
||||
}
|
||||
|
@ -136,8 +136,8 @@ static int HourCycle() {
|
||||
bool OSPreferences::ReadDateTimePattern(DateTimeFormatStyle aDateStyle,
|
||||
DateTimeFormatStyle aTimeStyle,
|
||||
const nsACString& aLocale,
|
||||
nsAString& aRetVal) {
|
||||
nsAutoString skeleton;
|
||||
nsACString& aRetVal) {
|
||||
nsAutoCString skeleton;
|
||||
if (!GetDateTimeSkeletonForStyle(aDateStyle, aTimeStyle, aLocale, skeleton)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -131,7 +131,7 @@ static CFLocaleRef CreateCFLocaleFor(const nsACString& aLocale) {
|
||||
bool OSPreferences::ReadDateTimePattern(DateTimeFormatStyle aDateStyle,
|
||||
DateTimeFormatStyle aTimeStyle,
|
||||
const nsACString& aLocale,
|
||||
nsAString& aRetVal) {
|
||||
nsACString& aRetVal) {
|
||||
CFLocaleRef locale = CreateCFLocaleFor(aLocale);
|
||||
if (!locale) {
|
||||
return false;
|
||||
@ -147,10 +147,12 @@ bool OSPreferences::ReadDateTimePattern(DateTimeFormatStyle aDateStyle,
|
||||
CFRelease(locale);
|
||||
|
||||
CFRange range = CFRangeMake(0, CFStringGetLength(format));
|
||||
aRetVal.SetLength(range.length);
|
||||
nsAutoString str;
|
||||
str.SetLength(range.length);
|
||||
CFStringGetCharacters(format, range,
|
||||
reinterpret_cast<UniChar*>(aRetVal.BeginWriting()));
|
||||
reinterpret_cast<UniChar*>(str.BeginWriting()));
|
||||
CFRelease(formatter);
|
||||
|
||||
aRetVal = NS_ConvertUTF16toUTF8(str);
|
||||
return true;
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ interface mozIOSPreferences : nsISupports
|
||||
* handle all scenarios, including with cases where we fail to retrieve
|
||||
* anything from the OS, here.
|
||||
*/
|
||||
AString getDateTimePattern(in long timeFormatStyle,
|
||||
in long dateFormatStyle,
|
||||
[optional] in ACString locale);
|
||||
ACString getDateTimePattern(in long timeFormatStyle,
|
||||
in long dateFormatStyle,
|
||||
[optional] in ACString locale);
|
||||
};
|
||||
|
@ -53,7 +53,7 @@ TEST(Intl_Locale_OSPreferences, GetRegionalPrefsLocales)
|
||||
*/
|
||||
TEST(Intl_Locale_OSPreferences, GetDateTimePattern)
|
||||
{
|
||||
nsAutoString pattern;
|
||||
nsAutoCString pattern;
|
||||
OSPreferences* osprefs = OSPreferences::GetInstance();
|
||||
|
||||
struct Test {
|
||||
@ -70,7 +70,6 @@ TEST(Intl_Locale_OSPreferences, GetDateTimePattern)
|
||||
|
||||
for (unsigned i = 0; i < mozilla::ArrayLength(tests); i++) {
|
||||
const Test& t = tests[i];
|
||||
nsAutoString pattern;
|
||||
if (NS_SUCCEEDED(osprefs->GetDateTimePattern(
|
||||
t.dateStyle, t.timeStyle, nsDependentCString(t.locale), pattern))) {
|
||||
ASSERT_TRUE((t.dateStyle == 0 && t.timeStyle == 0) || !pattern.IsEmpty());
|
||||
|
@ -204,7 +204,7 @@ static LCTYPE ToTimeLCType(OSPreferences::DateTimeFormatStyle aFormatStyle) {
|
||||
bool OSPreferences::ReadDateTimePattern(DateTimeFormatStyle aDateStyle,
|
||||
DateTimeFormatStyle aTimeStyle,
|
||||
const nsACString& aLocale,
|
||||
nsAString& aRetVal) {
|
||||
nsACString& aRetVal) {
|
||||
nsAutoString localeName;
|
||||
CopyASCIItoUTF16(aLocale, localeName);
|
||||
|
||||
@ -215,20 +215,13 @@ bool OSPreferences::ReadDateTimePattern(DateTimeFormatStyle aDateStyle,
|
||||
|
||||
// If both date and time are wanted, we'll initially read them into a
|
||||
// local string, and then insert them into the overall date+time pattern;
|
||||
// but if only one is needed we'll work directly with the return value.
|
||||
// Set 'str' to point to the string we will use to retrieve patterns
|
||||
// from Windows.
|
||||
nsAutoString tmpStr;
|
||||
nsAString* str;
|
||||
nsAutoString str;
|
||||
if (isDate && isTime) {
|
||||
if (!GetDateTimeConnectorPattern(aLocale, aRetVal)) {
|
||||
NS_WARNING("failed to get date/time connector");
|
||||
aRetVal.AssignLiteral(u"{1} {0}");
|
||||
aRetVal.AssignLiteral("{1} {0}");
|
||||
}
|
||||
str = &tmpStr;
|
||||
} else if (isDate || isTime) {
|
||||
str = &aRetVal;
|
||||
} else {
|
||||
} else if (!isDate && !isTime) {
|
||||
aRetVal.Truncate(0);
|
||||
return true;
|
||||
}
|
||||
@ -244,10 +237,10 @@ bool OSPreferences::ReadDateTimePattern(DateTimeFormatStyle aDateStyle,
|
||||
|
||||
// We're doing it to ensure the terminator will fit when Windows writes the
|
||||
// data to its output buffer. See bug 1358159 for details.
|
||||
str->SetLength(len);
|
||||
str.SetLength(len);
|
||||
GetLocaleInfoEx(reinterpret_cast<const wchar_t*>(localeName.BeginReading()),
|
||||
lcType, (WCHAR*)str->BeginWriting(), len);
|
||||
str->SetLength(len - 1); // -1 because len counts the null terminator
|
||||
lcType, (WCHAR*)str.BeginWriting(), len);
|
||||
str.SetLength(len - 1); // -1 because len counts the null terminator
|
||||
|
||||
// Windows uses "ddd" and "dddd" for abbreviated and full day names
|
||||
// respectively,
|
||||
@ -256,38 +249,40 @@ bool OSPreferences::ReadDateTimePattern(DateTimeFormatStyle aDateStyle,
|
||||
// http://userguide.icu-project.org/formatparse/datetime
|
||||
// So we fix that up here.
|
||||
nsAString::const_iterator start, pos, end;
|
||||
start = str->BeginReading(pos);
|
||||
str->EndReading(end);
|
||||
start = str.BeginReading(pos);
|
||||
str.EndReading(end);
|
||||
if (FindInReadable(u"dddd"_ns, pos, end)) {
|
||||
str->ReplaceLiteral(pos - start, 4, u"EEEE");
|
||||
str.ReplaceLiteral(pos - start, 4, u"EEEE");
|
||||
} else {
|
||||
pos = start;
|
||||
if (FindInReadable(u"ddd"_ns, pos, end)) {
|
||||
str->ReplaceLiteral(pos - start, 3, u"EEE");
|
||||
str.ReplaceLiteral(pos - start, 3, u"EEE");
|
||||
}
|
||||
}
|
||||
|
||||
// Also, Windows uses lowercase "g" or "gg" for era, but ICU wants uppercase
|
||||
// "G" (it would interpret "g" as "modified Julian day"!). So fix that.
|
||||
int32_t index = str->FindChar('g');
|
||||
int32_t index = str.FindChar('g');
|
||||
if (index >= 0) {
|
||||
str->Replace(index, 1, 'G');
|
||||
str.Replace(index, 1, 'G');
|
||||
// If it was a double "gg", just drop the second one.
|
||||
index++;
|
||||
if (str->CharAt(index) == 'g') {
|
||||
str->Cut(index, 1);
|
||||
if (str.CharAt(index) == 'g') {
|
||||
str.Cut(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// If time was also requested, we need to substitute the date pattern from
|
||||
// Windows into the date+time format that we have in aRetVal.
|
||||
if (isTime) {
|
||||
nsAString::const_iterator start, pos, end;
|
||||
nsACString::const_iterator start, pos, end;
|
||||
start = aRetVal.BeginReading(pos);
|
||||
aRetVal.EndReading(end);
|
||||
if (FindInReadable(u"{1}"_ns, pos, end)) {
|
||||
aRetVal.Replace(pos - start, 3, tmpStr);
|
||||
if (FindInReadable("{1}"_ns, pos, end)) {
|
||||
aRetVal.Replace(pos - start, 3, NS_ConvertUTF16toUTF8(str));
|
||||
}
|
||||
} else {
|
||||
aRetVal = NS_ConvertUTF16toUTF8(str);
|
||||
}
|
||||
}
|
||||
|
||||
@ -302,32 +297,34 @@ bool OSPreferences::ReadDateTimePattern(DateTimeFormatStyle aDateStyle,
|
||||
|
||||
// We're doing it to ensure the terminator will fit when Windows writes the
|
||||
// data to its output buffer. See bug 1358159 for details.
|
||||
str->SetLength(len);
|
||||
str.SetLength(len);
|
||||
GetLocaleInfoEx(reinterpret_cast<const wchar_t*>(localeName.BeginReading()),
|
||||
lcType, (WCHAR*)str->BeginWriting(), len);
|
||||
str->SetLength(len - 1);
|
||||
lcType, (WCHAR*)str.BeginWriting(), len);
|
||||
str.SetLength(len - 1);
|
||||
|
||||
// Windows uses "t" or "tt" for a "time marker" (am/pm indicator),
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/dd318148(v=vs.85).aspx
|
||||
// but in a CLDR/ICU-style pattern that should be "a".
|
||||
// http://userguide.icu-project.org/formatparse/datetime
|
||||
// So we fix that up here.
|
||||
int32_t index = str->FindChar('t');
|
||||
int32_t index = str.FindChar('t');
|
||||
if (index >= 0) {
|
||||
str->Replace(index, 1, 'a');
|
||||
str.Replace(index, 1, 'a');
|
||||
index++;
|
||||
if (str->CharAt(index) == 't') {
|
||||
str->Cut(index, 1);
|
||||
if (str.CharAt(index) == 't') {
|
||||
str.Cut(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (isDate) {
|
||||
nsAString::const_iterator start, pos, end;
|
||||
nsACString::const_iterator start, pos, end;
|
||||
start = aRetVal.BeginReading(pos);
|
||||
aRetVal.EndReading(end);
|
||||
if (FindInReadable(u"{0}"_ns, pos, end)) {
|
||||
aRetVal.Replace(pos - start, 3, tmpStr);
|
||||
if (FindInReadable("{0}"_ns, pos, end)) {
|
||||
aRetVal.Replace(pos - start, 3, NS_ConvertUTF16toUTF8(str));
|
||||
}
|
||||
} else {
|
||||
aRetVal = NS_ConvertUTF16toUTF8(str);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user