mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1214169 - Always use ICU in nsCollationMacUC. r=emk.
This commit is contained in:
parent
3c61437ab6
commit
41f1699bd8
@ -13,41 +13,24 @@
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsCollationMacUC, nsICollation)
|
||||
|
||||
nsCollationMacUC::nsCollationMacUC()
|
||||
nsCollationMacUC::nsCollationMacUC()
|
||||
: mInit(false)
|
||||
, mHasCollator(false)
|
||||
, mLocaleICU(nullptr)
|
||||
, mLocale(nullptr)
|
||||
, mLastStrength(-1)
|
||||
, mCollatorICU(nullptr)
|
||||
, mCollator(nullptr)
|
||||
, mBuffer(nullptr)
|
||||
, mBufferLen(1)
|
||||
, mUseICU(true)
|
||||
{
|
||||
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
if (prefs) {
|
||||
prefs->GetBoolPref("intl.collation.mac.use_icu", &mUseICU);
|
||||
}
|
||||
}
|
||||
{ }
|
||||
|
||||
nsCollationMacUC::~nsCollationMacUC()
|
||||
nsCollationMacUC::~nsCollationMacUC()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
nsresult res =
|
||||
#endif
|
||||
CleanUpCollator();
|
||||
NS_ASSERTION(NS_SUCCEEDED(res), "CleanUpCollator failed");
|
||||
if (mUseICU) {
|
||||
if (mLocaleICU) {
|
||||
free(mLocaleICU);
|
||||
mLocaleICU = nullptr;
|
||||
}
|
||||
} else {
|
||||
if (mBuffer) {
|
||||
free(mBuffer);
|
||||
mBuffer = nullptr;
|
||||
}
|
||||
if (mLocaleICU) {
|
||||
free(mLocaleICU);
|
||||
mLocaleICU = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,21 +68,6 @@ nsresult nsCollationMacUC::ConvertStrength(const int32_t aNSStrength,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsCollationMacUC::StrengthToOptions(const int32_t aStrength,
|
||||
UCCollateOptions* aOptions)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aOptions);
|
||||
NS_ENSURE_TRUE((aStrength < 4), NS_ERROR_FAILURE);
|
||||
// set our default collation options
|
||||
UCCollateOptions options = kUCCollateStandardOptions | kUCCollatePunctuationSignificantMask;
|
||||
if (aStrength & kCollationCaseInsensitiveAscii)
|
||||
options |= kUCCollateCaseInsensitiveMask;
|
||||
if (aStrength & kCollationAccentInsenstive)
|
||||
options |= kUCCollateDiacritInsensitiveMask;
|
||||
*aOptions = options;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsCollationMacUC::ConvertLocaleICU(nsILocale* aNSLocale, char** aICULocale)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aNSLocale);
|
||||
@ -122,25 +90,7 @@ nsresult nsCollationMacUC::ConvertLocaleICU(nsILocale* aNSLocale, char** aICULoc
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsCollationMacUC::ConvertLocale(nsILocale* aNSLocale, LocaleRef* aMacLocale)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aNSLocale);
|
||||
NS_ENSURE_ARG_POINTER(aMacLocale);
|
||||
|
||||
nsAutoString localeString;
|
||||
nsresult res = aNSLocale->GetCategory(NS_LITERAL_STRING("NSILOCALE_COLLATE"), localeString);
|
||||
NS_ENSURE_TRUE(NS_SUCCEEDED(res) && !localeString.IsEmpty(),
|
||||
NS_ERROR_FAILURE);
|
||||
NS_LossyConvertUTF16toASCII tmp(localeString);
|
||||
tmp.ReplaceChar('-', '_');
|
||||
OSStatus err;
|
||||
err = ::LocaleRefFromLocaleString(tmp.get(), aMacLocale);
|
||||
NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsCollationMacUC::EnsureCollator(const int32_t newStrength)
|
||||
nsresult nsCollationMacUC::EnsureCollator(const int32_t newStrength)
|
||||
{
|
||||
NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED);
|
||||
if (mHasCollator && (mLastStrength == newStrength))
|
||||
@ -150,42 +100,31 @@ nsresult nsCollationMacUC::EnsureCollator(const int32_t newStrength)
|
||||
res = CleanUpCollator();
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
if (mUseICU) {
|
||||
NS_ENSURE_TRUE(mLocaleICU, NS_ERROR_NOT_INITIALIZED);
|
||||
NS_ENSURE_TRUE(mLocaleICU, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
UErrorCode status;
|
||||
status = U_ZERO_ERROR;
|
||||
mCollatorICU = ucol_open(mLocaleICU, &status);
|
||||
NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
|
||||
UErrorCode status;
|
||||
status = U_ZERO_ERROR;
|
||||
mCollatorICU = ucol_open(mLocaleICU, &status);
|
||||
NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
|
||||
|
||||
UCollationStrength strength;
|
||||
UColAttributeValue caseLevel;
|
||||
res = ConvertStrength(newStrength, &strength, &caseLevel);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
UCollationStrength strength;
|
||||
UColAttributeValue caseLevel;
|
||||
res = ConvertStrength(newStrength, &strength, &caseLevel);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
status = U_ZERO_ERROR;
|
||||
ucol_setAttribute(mCollatorICU, UCOL_STRENGTH, strength, &status);
|
||||
NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
|
||||
ucol_setAttribute(mCollatorICU, UCOL_CASE_LEVEL, caseLevel, &status);
|
||||
NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
|
||||
ucol_setAttribute(mCollatorICU, UCOL_ALTERNATE_HANDLING, UCOL_DEFAULT, &status);
|
||||
NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
|
||||
ucol_setAttribute(mCollatorICU, UCOL_NUMERIC_COLLATION, UCOL_OFF, &status);
|
||||
NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
|
||||
ucol_setAttribute(mCollatorICU, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
|
||||
NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
|
||||
ucol_setAttribute(mCollatorICU, UCOL_CASE_FIRST, UCOL_DEFAULT, &status);
|
||||
NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
|
||||
} else {
|
||||
OSStatus err;
|
||||
UCCollateOptions newOptions;
|
||||
res = StrengthToOptions(newStrength, &newOptions);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
LocaleOperationVariant opVariant = 0; // default variant for now
|
||||
err = ::UCCreateCollator(mLocale, opVariant, newOptions, &mCollator);
|
||||
NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE);
|
||||
}
|
||||
status = U_ZERO_ERROR;
|
||||
ucol_setAttribute(mCollatorICU, UCOL_STRENGTH, strength, &status);
|
||||
NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
|
||||
ucol_setAttribute(mCollatorICU, UCOL_CASE_LEVEL, caseLevel, &status);
|
||||
NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
|
||||
ucol_setAttribute(mCollatorICU, UCOL_ALTERNATE_HANDLING, UCOL_DEFAULT, &status);
|
||||
NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
|
||||
ucol_setAttribute(mCollatorICU, UCOL_NUMERIC_COLLATION, UCOL_OFF, &status);
|
||||
NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
|
||||
ucol_setAttribute(mCollatorICU, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
|
||||
NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
|
||||
ucol_setAttribute(mCollatorICU, UCOL_CASE_FIRST, UCOL_DEFAULT, &status);
|
||||
NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
|
||||
|
||||
mHasCollator = true;
|
||||
|
||||
@ -196,14 +135,8 @@ nsresult nsCollationMacUC::EnsureCollator(const int32_t newStrength)
|
||||
nsresult nsCollationMacUC::CleanUpCollator(void)
|
||||
{
|
||||
if (mHasCollator) {
|
||||
if (mUseICU) {
|
||||
ucol_close(mCollatorICU);
|
||||
mHasCollator = false;
|
||||
} else {
|
||||
OSStatus err = ::UCDisposeCollator(&mCollator);
|
||||
mHasCollator = false;
|
||||
NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE);
|
||||
}
|
||||
ucol_close(mCollatorICU);
|
||||
mHasCollator = false;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -223,11 +156,7 @@ NS_IMETHODIMP nsCollationMacUC::Initialize(nsILocale* locale)
|
||||
locale = appLocale;
|
||||
}
|
||||
|
||||
if (mUseICU) {
|
||||
rv = ConvertLocaleICU(locale, &mLocaleICU);
|
||||
} else {
|
||||
rv = ConvertLocale(locale, &mLocale);
|
||||
}
|
||||
rv = ConvertLocaleICU(locale, &mLocaleICU);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mInit = true;
|
||||
@ -246,102 +175,55 @@ NS_IMETHODIMP nsCollationMacUC::AllocateRawSortKey(int32_t strength, const nsASt
|
||||
|
||||
uint32_t stringInLen = stringIn.Length();
|
||||
|
||||
if (mUseICU) {
|
||||
const UChar* str = (const UChar*)PromiseFlatString(stringIn).get();
|
||||
const UChar* str = (const UChar*)PromiseFlatString(stringIn).get();
|
||||
|
||||
int32_t keyLength = ucol_getSortKey(mCollatorICU, str, stringInLen, nullptr, 0);
|
||||
NS_ENSURE_TRUE((stringInLen == 0 || keyLength > 0), NS_ERROR_FAILURE);
|
||||
int32_t keyLength = ucol_getSortKey(mCollatorICU, str, stringInLen, nullptr, 0);
|
||||
NS_ENSURE_TRUE((stringInLen == 0 || keyLength > 0), NS_ERROR_FAILURE);
|
||||
|
||||
// Since key is freed elsewhere with PR_Free, allocate with PR_Malloc.
|
||||
uint8_t* newKey = (uint8_t*)PR_Malloc(keyLength + 1);
|
||||
if (!newKey) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
keyLength = ucol_getSortKey(mCollatorICU, str, stringInLen, newKey, keyLength + 1);
|
||||
NS_ENSURE_TRUE((stringInLen == 0 || keyLength > 0), NS_ERROR_FAILURE);
|
||||
|
||||
*key = newKey;
|
||||
*outLen = keyLength;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
uint32_t maxKeyLen = (1 + stringInLen) * kCollationValueSizeFactor * sizeof(UCCollationValue);
|
||||
if (maxKeyLen > mBufferLen) {
|
||||
uint32_t newBufferLen = mBufferLen;
|
||||
do {
|
||||
newBufferLen *= 2;
|
||||
} while (newBufferLen < maxKeyLen);
|
||||
void* newBuffer = malloc(newBufferLen);
|
||||
if (!newBuffer) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if (mBuffer) {
|
||||
free(mBuffer);
|
||||
mBuffer = nullptr;
|
||||
}
|
||||
mBuffer = newBuffer;
|
||||
mBufferLen = newBufferLen;
|
||||
}
|
||||
|
||||
ItemCount actual;
|
||||
OSStatus err = ::UCGetCollationKey(mCollator, (const UniChar*) PromiseFlatString(stringIn).get(),
|
||||
(UniCharCount) stringInLen,
|
||||
(ItemCount) (mBufferLen / sizeof(UCCollationValue)),
|
||||
&actual, (UCCollationValue *)mBuffer);
|
||||
NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE);
|
||||
|
||||
uint32_t keyLength = actual * sizeof(UCCollationValue);
|
||||
// Since key is freed elsewhere with PR_Free, allocate with PR_Malloc.
|
||||
void* newKey = PR_Malloc(keyLength);
|
||||
uint8_t* newKey = (uint8_t*)PR_Malloc(keyLength + 1);
|
||||
if (!newKey) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
memcpy(newKey, mBuffer, keyLength);
|
||||
*key = (uint8_t *)newKey;
|
||||
keyLength = ucol_getSortKey(mCollatorICU, str, stringInLen, newKey, keyLength + 1);
|
||||
NS_ENSURE_TRUE((stringInLen == 0 || keyLength > 0), NS_ERROR_FAILURE);
|
||||
|
||||
*key = newKey;
|
||||
*outLen = keyLength;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCollationMacUC::CompareString(int32_t strength, const nsAString& string1,
|
||||
const nsAString& string2, int32_t* result)
|
||||
const nsAString& string2, int32_t* result)
|
||||
{
|
||||
NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED);
|
||||
NS_ENSURE_ARG_POINTER(result);
|
||||
*result = 0;
|
||||
|
||||
nsresult res = EnsureCollator(strength);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
nsresult rv = EnsureCollator(strength);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (mUseICU) {
|
||||
UCollationResult uresult;
|
||||
uresult = ucol_strcoll(mCollatorICU,
|
||||
(const UChar*)PromiseFlatString(string1).get(), string1.Length(),
|
||||
(const UChar*)PromiseFlatString(string2).get(), string2.Length());
|
||||
int32_t res;
|
||||
switch (uresult) {
|
||||
case UCOL_LESS: res = -1; break;
|
||||
case UCOL_EQUAL: res = 0; break;
|
||||
case UCOL_GREATER: res = 1; break;
|
||||
default: MOZ_CRASH("ucol_strcoll returned bad UCollationResult");
|
||||
}
|
||||
*result = res;
|
||||
return NS_OK;
|
||||
UCollationResult uresult;
|
||||
uresult = ucol_strcoll(mCollatorICU,
|
||||
(const UChar*)PromiseFlatString(string1).get(), string1.Length(),
|
||||
(const UChar*)PromiseFlatString(string2).get(), string2.Length());
|
||||
int32_t res;
|
||||
switch (uresult) {
|
||||
case UCOL_LESS:
|
||||
res = -1;
|
||||
break;
|
||||
case UCOL_EQUAL:
|
||||
res = 0;
|
||||
break;
|
||||
case UCOL_GREATER:
|
||||
res = 1;
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("ucol_strcoll returned bad UCollationResult");
|
||||
}
|
||||
|
||||
*result = 0;
|
||||
|
||||
OSStatus err;
|
||||
err = ::UCCompareText(mCollator,
|
||||
(const UniChar *) PromiseFlatString(string1).get(), (UniCharCount) string1.Length(),
|
||||
(const UniChar *) PromiseFlatString(string2).get(), (UniCharCount) string2.Length(),
|
||||
nullptr, (SInt32*) result);
|
||||
|
||||
NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE);
|
||||
*result = res;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -355,26 +237,15 @@ NS_IMETHODIMP nsCollationMacUC::CompareRawSortKey(const uint8_t* key1, uint32_t
|
||||
NS_ENSURE_ARG_POINTER(result);
|
||||
*result = 0;
|
||||
|
||||
if (mUseICU) {
|
||||
int32_t tmpResult = strcmp((const char*)key1, (const char*)key2);
|
||||
int32_t res;
|
||||
if (tmpResult < 0) {
|
||||
int32_t tmpResult = strcmp((const char*)key1, (const char*)key2);
|
||||
int32_t res;
|
||||
if (tmpResult < 0) {
|
||||
res = -1;
|
||||
} else if (tmpResult > 0) {
|
||||
} else if (tmpResult > 0) {
|
||||
res = 1;
|
||||
} else {
|
||||
} else {
|
||||
res = 0;
|
||||
}
|
||||
*result = res;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
OSStatus err;
|
||||
err = ::UCCompareCollationKeys((const UCCollationValue*) key1, (ItemCount) len1,
|
||||
(const UCCollationValue*) key2, (ItemCount) len2,
|
||||
nullptr, (SInt32*) result);
|
||||
|
||||
NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE);
|
||||
|
||||
*result = res;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -11,18 +11,10 @@
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#include "unicode/ucol.h"
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
// Maximum number of characters for a buffer to remember
|
||||
// the generated collation key.
|
||||
const uint32_t kCacheSize = 128;
|
||||
// According to the documentation, the length of the key should typically be
|
||||
// at least 5 * textLength, but 6* would be safer.
|
||||
const uint32_t kCollationValueSizeFactor = 6;
|
||||
|
||||
class nsCollationMacUC final : public nsICollation {
|
||||
|
||||
public:
|
||||
public:
|
||||
nsCollationMacUC();
|
||||
|
||||
// nsISupports interface
|
||||
@ -32,15 +24,12 @@ public:
|
||||
NS_DECL_NSICOLLATION
|
||||
|
||||
protected:
|
||||
~nsCollationMacUC();
|
||||
~nsCollationMacUC();
|
||||
|
||||
nsresult ConvertLocaleICU(nsILocale* aNSLocale, char** aICULocale);
|
||||
nsresult ConvertLocale(nsILocale* aNSLocale, LocaleRef* aMacLocale);
|
||||
nsresult ConvertStrength(const int32_t aStrength,
|
||||
UCollationStrength* aStrengthOut,
|
||||
UColAttributeValue* aCaseLevelOut);
|
||||
nsresult StrengthToOptions(const int32_t aStrength,
|
||||
UCCollateOptions* aOptions);
|
||||
nsresult EnsureCollator(const int32_t newStrength);
|
||||
nsresult CleanUpCollator(void);
|
||||
|
||||
@ -48,13 +37,8 @@ private:
|
||||
bool mInit;
|
||||
bool mHasCollator;
|
||||
char* mLocaleICU;
|
||||
LocaleRef mLocale;
|
||||
int32_t mLastStrength;
|
||||
UCollator* mCollatorICU;
|
||||
CollatorRef mCollator;
|
||||
void *mBuffer; // temporary buffer to generate collation keys
|
||||
uint32_t mBufferLen; // byte length of buffer
|
||||
bool mUseICU;
|
||||
};
|
||||
|
||||
#endif /* nsCollationMacUC_h_ */
|
||||
|
@ -2,7 +2,8 @@ var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function check_sort() {
|
||||
function run_test()
|
||||
{
|
||||
var input = [
|
||||
"Argentina",
|
||||
"Oerlikon",
|
||||
@ -80,29 +81,3 @@ function check_sort() {
|
||||
"日本",
|
||||
]);
|
||||
}
|
||||
|
||||
function test_default() {
|
||||
Services.prefs.clearUserPref("intl.collation.mac.use_icu");
|
||||
check_sort();
|
||||
}
|
||||
|
||||
function test_ICU() {
|
||||
Services.prefs.setBoolPref("intl.collation.mac.use_icu", true);
|
||||
check_sort();
|
||||
}
|
||||
|
||||
function test_CoreServices() {
|
||||
Services.prefs.setBoolPref("intl.collation.mac.use_icu", false);
|
||||
check_sort();
|
||||
}
|
||||
|
||||
function run_test()
|
||||
{
|
||||
test_default();
|
||||
test_ICU();
|
||||
if (Services.sysinfo.getProperty("arch") == "x86") {
|
||||
test_CoreServices();
|
||||
}
|
||||
|
||||
Services.prefs.clearUserPref("intl.collation.mac.use_icu");
|
||||
}
|
||||
|
@ -4948,9 +4948,6 @@ pref("dom.presentation.discovery.timeout_ms", 10000);
|
||||
pref("dom.presentation.discoverable", false);
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
// Use raw ICU instead of CoreServices API in Unicode collation
|
||||
pref("intl.collation.mac.use_icu", true);
|
||||
|
||||
#if !defined(RELEASE_BUILD) || defined(DEBUG)
|
||||
// In non-release builds we crash by default on insecure text input (when a
|
||||
// password editor has focus but secure event input isn't enabled). The
|
||||
|
Loading…
Reference in New Issue
Block a user