Bug 1719550 - Remove nsCollation; r=platform-i18n-reviewers,nordzilla

All the call sites now use mozilla::intl::Collator

Differential Revision: https://phabricator.services.mozilla.com/D121435
This commit is contained in:
Greg Tatum 2021-08-10 16:01:19 +00:00
parent d389d769f4
commit 418e9b4700
10 changed files with 0 additions and 569 deletions

View File

@ -23,10 +23,4 @@ Classes = [
'headers': ['mozilla/intl/OSPreferences.h'],
'constructor': 'mozilla::intl::OSPreferences::GetInstanceAddRefed',
},
{
'cid': '{a1b72850-a999-11d2-9119-006008a6edf6}',
'contract_ids': ['@mozilla.org/intl/collation-factory;1'],
'type': 'nsCollationFactory',
'headers': ['/intl/locale/nsCollationFactory.h'],
},
]

View File

@ -20,14 +20,12 @@ elif toolkit == "android":
XPIDL_SOURCES += [
"mozILocaleService.idl",
"mozIOSPreferences.idl",
"nsICollation.idl",
]
XPIDL_MODULE = "locale"
EXPORTS += [
"DateTimeFormat.h",
"nsCollationCID.h",
"nsLanguageAtomService.h",
"nsUConvPropertySearch.h",
]
@ -44,8 +42,6 @@ UNIFIED_SOURCES += [
"DateTimeFormat.cpp",
"LocaleService.cpp",
"MozLocale.cpp",
"nsCollation.cpp",
"nsCollationFactory.cpp",
"nsLanguageAtomService.cpp",
"nsUConvPropertySearch.cpp",
"OSPreferences.cpp",

View File

@ -1,215 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsCollation.h"
#include "mozilla/intl/LocaleService.h"
#include "nsString.h"
NS_IMPL_ISUPPORTS(nsCollation, nsICollation)
nsCollation::nsCollation()
: mInit(false),
mHasCollator(false),
mLastStrength(-1),
mCollatorICU(nullptr) {}
nsCollation::~nsCollation() {
#ifdef DEBUG
nsresult res =
#endif
CleanUpCollator();
NS_ASSERTION(NS_SUCCEEDED(res), "CleanUpCollator failed");
}
nsresult nsCollation::ConvertStrength(const int32_t aNSStrength,
UCollationStrength* aICUStrength,
UColAttributeValue* aCaseLevelOut) {
NS_ENSURE_ARG_POINTER(aICUStrength);
NS_ENSURE_TRUE((aNSStrength < 4), NS_ERROR_FAILURE);
UCollationStrength strength = UCOL_DEFAULT;
UColAttributeValue caseLevel = UCOL_OFF;
switch (aNSStrength) {
case kCollationCaseInSensitive:
strength = UCOL_PRIMARY;
break;
case kCollationCaseInsensitiveAscii:
strength = UCOL_SECONDARY;
break;
case kCollationAccentInsenstive:
caseLevel = UCOL_ON;
strength = UCOL_PRIMARY;
break;
case kCollationCaseSensitive:
strength = UCOL_TERTIARY;
break;
default:
NS_WARNING("Bad aNSStrength passed to ConvertStrength.");
return NS_ERROR_FAILURE;
}
*aICUStrength = strength;
*aCaseLevelOut = caseLevel;
return NS_OK;
}
nsresult nsCollation::EnsureCollator(const int32_t newStrength) {
NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED);
if (mHasCollator && (mLastStrength == newStrength)) return NS_OK;
nsresult res;
res = CleanUpCollator();
NS_ENSURE_SUCCESS(res, res);
UErrorCode status;
status = U_ZERO_ERROR;
mCollatorICU = ucol_open(mLocale.get(), &status);
NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
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);
mHasCollator = true;
mLastStrength = newStrength;
return NS_OK;
}
nsresult nsCollation::CleanUpCollator(void) {
if (mHasCollator) {
ucol_close(mCollatorICU);
mHasCollator = false;
}
return NS_OK;
}
NS_IMETHODIMP
nsCollation::Initialize(const nsACString& locale) {
NS_ENSURE_TRUE((!mInit), NS_ERROR_ALREADY_INITIALIZED);
// Check whether locale parameter is valid. If no, use application locale
UErrorCode status = U_ZERO_ERROR;
UCollator* collator = ucol_open(PromiseFlatCString(locale).get(), &status);
if (U_SUCCESS(status)) {
mLocale = locale;
} else {
status = U_ZERO_ERROR;
mozilla::LocaleService::GetInstance()->GetAppLocaleAsBCP47(mLocale);
collator = ucol_open(mLocale.get(), &status);
if (NS_WARN_IF(U_FAILURE(status))) {
return NS_ERROR_UNEXPECTED;
}
}
ucol_close(collator);
mInit = true;
return NS_OK;
}
NS_IMETHODIMP
nsCollation::AllocateRawSortKey(int32_t strength, const nsAString& stringIn,
nsTArray<uint8_t>& key) {
NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED);
nsresult res = EnsureCollator(strength);
NS_ENSURE_SUCCESS(res, res);
uint32_t stringInLen = stringIn.Length();
const UChar* str = (const UChar*)stringIn.BeginReading();
int32_t keyLength =
ucol_getSortKey(mCollatorICU, str, stringInLen, nullptr, 0);
NS_ENSURE_TRUE((stringInLen == 0 || keyLength > 0), NS_ERROR_FAILURE);
key.SetLength(keyLength + 1);
keyLength = ucol_getSortKey(mCollatorICU, str, stringInLen, key.Elements(),
keyLength + 1);
NS_ENSURE_TRUE((stringInLen == 0 || keyLength > 0), NS_ERROR_FAILURE);
key.SetLength(keyLength);
return NS_OK;
}
NS_IMETHODIMP
nsCollation::CompareString(int32_t strength, const nsAString& string1,
const nsAString& string2, int32_t* result) {
NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED);
NS_ENSURE_ARG_POINTER(result);
*result = 0;
nsresult rv = EnsureCollator(strength);
NS_ENSURE_SUCCESS(rv, rv);
UCollationResult uresult;
uresult = ucol_strcoll(mCollatorICU, (const UChar*)string1.BeginReading(),
string1.Length(), (const UChar*)string2.BeginReading(),
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;
}
NS_IMETHODIMP
nsCollation::CompareRawSortKey(const nsTArray<uint8_t>& key1,
const nsTArray<uint8_t>& key2, int32_t* result) {
NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED);
NS_ENSURE_ARG_POINTER(result);
*result = 0;
size_t minLength = std::min(key1.Length(), key2.Length());
int32_t tmpResult = strncmp((const char*)key1.Elements(),
(const char*)key2.Elements(), minLength);
int32_t res;
if (tmpResult < 0) {
res = -1;
} else if (tmpResult > 0) {
res = 1;
} else if (key1.Length() > minLength) {
// First string contains second one, so comes later, hence return > 0.
res = 1;
} else if (key2.Length() > minLength) {
// First string is a substring of second one, so comes earlier,
// hence return < 0.
res = -1;
} else {
res = 0;
}
*result = res;
return NS_OK;
}

View File

@ -1,43 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsCollation_h_
#define nsCollation_h_
#include "mozilla/Attributes.h"
#include "nsICollation.h"
#include "nsCollationFactory.h"
#include "nsString.h"
#include "unicode/ucol.h"
class nsCollation final : public nsICollation {
public:
nsCollation();
// nsISupports interface
NS_DECL_ISUPPORTS
// nsICollation interface
NS_DECL_NSICOLLATION
protected:
~nsCollation();
nsresult ConvertStrength(const int32_t aStrength,
UCollationStrength* aStrengthOut,
UColAttributeValue* aCaseLevelOut);
nsresult EnsureCollator(const int32_t newStrength);
nsresult CleanUpCollator(void);
private:
bool mInit;
bool mHasCollator;
nsCString mLocale;
int32_t mLastStrength;
UCollator* mCollatorICU;
};
#endif /* nsCollation_h_ */

View File

@ -1,21 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsCollationCID_h__
#define nsCollationCID_h__
#include "nscore.h"
#include "nsISupports.h"
// {A1B72850-A999-11d2-9119-006008A6EDF6}
#define NS_COLLATIONFACTORY_CID \
{ \
0xa1b72850, 0xa999, 0x11d2, { \
0x91, 0x19, 0x0, 0x60, 0x8, 0xa6, 0xed, 0xf6 \
} \
}
#define NS_COLLATIONFACTORY_CONTRACTID "@mozilla.org/intl/collation-factory;1"
#endif // nsCollationCID_h__

View File

@ -1,33 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsCollationFactory.h"
#include "nsCollation.h"
#include "nsServiceManagerUtils.h"
#include "mozilla/intl/LocaleService.h"
////////////////////////////////////////////////////////////////////////////////
NS_IMPL_ISUPPORTS(nsCollationFactory, nsICollationFactory)
nsresult nsCollationFactory::CreateCollation(nsICollation** instancePtr) {
nsAutoCString appLocale;
mozilla::intl::LocaleService::GetInstance()->GetAppLocaleAsBCP47(appLocale);
return CreateCollationForLocale(appLocale, instancePtr);
}
nsresult nsCollationFactory::CreateCollationForLocale(
const nsACString& locale, nsICollation** instancePtr) {
// Create a collation interface instance.
//
nsCOMPtr<nsICollation> inst = new nsCollation();
inst->Initialize(locale);
inst.forget(instancePtr);
return NS_OK;
}

View File

@ -1,26 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsCollationFactory_h__
#define nsCollationFactory_h__
#include "nsICollation.h"
#include "nsCOMPtr.h"
#include "mozilla/Attributes.h"
// Create a collation interface for the current app's locale.
//
class nsCollationFactory final : public nsICollationFactory {
~nsCollationFactory() = default;
public:
NS_DECL_ISUPPORTS
NS_DECL_NSICOLLATIONFACTORY
nsCollationFactory() = default;
};
#endif /* nsCollationFactory_h__ */

View File

@ -1,63 +0,0 @@
/* -*- Mode: idl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
interface nsICollation;
[scriptable, uuid(04971e14-d6b3-4ada-8cbb-c3a13842b349)]
interface nsICollationFactory : nsISupports
{
/**
* Create a new collation for the current application locale.
*
* @return A new collation.
*/
nsICollation CreateCollation();
/**
* Create a new collation for a given locale.
*
* @return A new collation.
*/
nsICollation CreateCollationForLocale(in ACString locale);
};
[scriptable, uuid(b0132cc0-3786-4557-9874-910d7def5f93)]
interface nsICollation : nsISupports {
// use the primary comparison for the given locale - no flags
const long kCollationStrengthDefault = 0;
// do not consider case differences when doing the comparison i.e. A=a)
const long kCollationCaseInsensitiveAscii = 1;
// do not consider accent differences when doing the comparison a=á)
const long kCollationAccentInsenstive = 2;
// case sensitive collation (default)
const long kCollationCaseSensitive = kCollationStrengthDefault;
// case insensitive collation
const long kCollationCaseInSensitive = (kCollationCaseInsensitiveAscii | kCollationAccentInsenstive);
// init this interface to a specified locale (should only be called by collation factory)
void initialize(in ACString locale);
// compare two strings
// result is same as strcmp
long compareString(in long strength, in AString string1, in AString string2);
// allocate sort key from input string
// returns newly allocated key
[noscript] Array<octet> allocateRawSortKey(in long strength,
in AString stringIn);
// compare two sort keys
// result is same as strcmp
[noscript] long compareRawSortKey(in Array<octet> key1,
in Array<octet> key2);
};

View File

@ -1,157 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gtest/gtest.h"
#include "nsCollationCID.h"
#include "nsComponentManagerUtils.h"
#include "nsCOMPtr.h"
#include "nsICollation.h"
#include "nsString.h"
#include "nsTArray.h"
TEST(Collation, AllocateRowSortKey)
{
nsCOMPtr<nsICollationFactory> colFactory =
do_CreateInstance(NS_COLLATIONFACTORY_CONTRACTID);
ASSERT_TRUE(colFactory);
// Don't throw error even if locale name is invalid
nsCOMPtr<nsICollation> collator;
nsresult rv = colFactory->CreateCollationForLocale("$languageName"_ns,
getter_AddRefs(collator));
ASSERT_TRUE(NS_SUCCEEDED(rv));
nsTArray<uint8_t> sortKey1;
// Don't throw error even if locale name is invalid
rv = collator->AllocateRawSortKey(nsICollation::kCollationStrengthDefault,
u"ABC"_ns, sortKey1);
ASSERT_TRUE(NS_SUCCEEDED(rv));
nsTArray<uint8_t> sortKey2;
// Don't throw error even if locale name is invalid
rv = collator->AllocateRawSortKey(nsICollation::kCollationStrengthDefault,
u"DEF"_ns, sortKey2);
ASSERT_TRUE(NS_SUCCEEDED(rv));
int32_t result;
rv = collator->CompareRawSortKey(sortKey1, sortKey2, &result);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_TRUE(result < 0);
}
class CollationComparator final {
public:
explicit CollationComparator(nsICollation* aCollation)
: mCollation(aCollation) {}
bool Equals(const nsString& a, const nsString& b) const {
int32_t result = 0;
mCollation->CompareString(nsICollation::kCollationStrengthDefault, a, b,
&result);
return result == 0;
}
bool LessThan(const nsString& a, const nsString& b) const {
int32_t result = 0;
mCollation->CompareString(nsICollation::kCollationStrengthDefault, a, b,
&result);
return result < 0;
}
private:
nsCOMPtr<nsICollation> mCollation;
};
TEST(Collation, CompareString)
{
nsTArray<nsString> input;
input.AppendElement(u"Argentina"_ns);
input.AppendElement(u"Oerlikon"_ns);
input.AppendElement(u"Offenbach"_ns);
input.AppendElement(u"Sverige"_ns);
input.AppendElement(u"Vaticano"_ns);
input.AppendElement(u"Zimbabwe"_ns);
input.AppendElement(u"la France"_ns);
input.AppendElement(u"\u00a1viva Espa\u00f1a!"_ns);
input.AppendElement(u"\u00d6sterreich"_ns);
input.AppendElement(u"\u4e2d\u56fd"_ns);
input.AppendElement(u"\u65e5\u672c"_ns);
input.AppendElement(u"\ud55c\uad6d"_ns);
nsCOMPtr<nsICollationFactory> colFactory =
do_CreateInstance(NS_COLLATIONFACTORY_CONTRACTID);
ASSERT_TRUE(colFactory);
// Locale en-US; default options.
nsCOMPtr<nsICollation> collation;
colFactory->CreateCollationForLocale("en-US"_ns, getter_AddRefs(collation));
ASSERT_TRUE(collation);
{
CollationComparator comparator(collation);
input.Sort(comparator);
ASSERT_TRUE(input[0].Equals(u"\u00a1viva Espa\u00f1a!"_ns));
ASSERT_TRUE(input[1].Equals(u"Argentina"_ns));
ASSERT_TRUE(input[2].Equals(u"la France"_ns));
ASSERT_TRUE(input[3].Equals(u"Oerlikon"_ns));
ASSERT_TRUE(input[4].Equals(u"Offenbach"_ns));
ASSERT_TRUE(input[5].Equals(u"\u00d6sterreich"_ns));
ASSERT_TRUE(input[6].Equals(u"Sverige"_ns));
ASSERT_TRUE(input[7].Equals(u"Vaticano"_ns));
ASSERT_TRUE(input[8].Equals(u"Zimbabwe"_ns));
ASSERT_TRUE(input[9].Equals(u"\ud55c\uad6d"_ns));
ASSERT_TRUE(input[10].Equals(u"\u4e2d\u56fd"_ns));
ASSERT_TRUE(input[11].Equals(u"\u65e5\u672c"_ns));
}
// Locale sv-SE; default options.
// Swedish treats "Ö" as a separate character, which sorts after "Z".
colFactory->CreateCollationForLocale("sv-SE"_ns, getter_AddRefs(collation));
ASSERT_TRUE(collation);
{
CollationComparator comparator(collation);
input.Sort(comparator);
ASSERT_TRUE(input[0].Equals(u"\u00a1viva Espa\u00f1a!"_ns));
ASSERT_TRUE(input[1].Equals(u"Argentina"_ns));
ASSERT_TRUE(input[2].Equals(u"la France"_ns));
ASSERT_TRUE(input[3].Equals(u"Oerlikon"_ns));
ASSERT_TRUE(input[4].Equals(u"Offenbach"_ns));
ASSERT_TRUE(input[5].Equals(u"Sverige"_ns));
ASSERT_TRUE(input[6].Equals(u"Vaticano"_ns));
ASSERT_TRUE(input[7].Equals(u"Zimbabwe"_ns));
ASSERT_TRUE(input[8].Equals(u"\u00d6sterreich"_ns));
ASSERT_TRUE(input[9].Equals(u"\ud55c\uad6d"_ns));
ASSERT_TRUE(input[10].Equals(u"\u4e2d\u56fd"_ns));
ASSERT_TRUE(input[11].Equals(u"\u65e5\u672c"_ns));
}
// Locale de-DE; default options.
// In German standard sorting, umlauted characters are treated as variants
// of their base characters: ä ≅ a, ö ≅ o, ü ≅ u.
colFactory->CreateCollationForLocale("de-DE"_ns, getter_AddRefs(collation));
ASSERT_TRUE(collation);
{
CollationComparator comparator(collation);
input.Sort(comparator);
ASSERT_TRUE(input[0].Equals(u"\u00a1viva Espa\u00f1a!"_ns));
ASSERT_TRUE(input[1].Equals(u"Argentina"_ns));
ASSERT_TRUE(input[2].Equals(u"la France"_ns));
ASSERT_TRUE(input[3].Equals(u"Oerlikon"_ns));
ASSERT_TRUE(input[4].Equals(u"Offenbach"_ns));
ASSERT_TRUE(input[5].Equals(u"\u00d6sterreich"_ns));
ASSERT_TRUE(input[6].Equals(u"Sverige"_ns));
ASSERT_TRUE(input[7].Equals(u"Vaticano"_ns));
ASSERT_TRUE(input[8].Equals(u"Zimbabwe"_ns));
ASSERT_TRUE(input[9].Equals(u"\ud55c\uad6d"_ns));
ASSERT_TRUE(input[10].Equals(u"\u4e2d\u56fd"_ns));
ASSERT_TRUE(input[11].Equals(u"\u65e5\u672c"_ns));
}
}

View File

@ -5,7 +5,6 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
UNIFIED_SOURCES += [
"TestCollation.cpp",
"TestDateTimeFormat.cpp",
"TestLocaleService.cpp",
"TestLocaleServiceNegotiate.cpp",