зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1719550 - Unify collator in mozStorageService and SQLCollations; r=platform-i18n-reviewers,nordzilla
Differential Revision: https://phabricator.services.mozilla.com/D121432
This commit is contained in:
Родитель
a7f0aa2461
Коммит
ee5176c26e
|
@ -5,9 +5,12 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/intl/Collator.h"
|
||||
|
||||
#include "SQLCollations.h"
|
||||
|
||||
using mozilla::intl::Collator;
|
||||
|
||||
namespace mozilla {
|
||||
namespace storage {
|
||||
|
||||
|
@ -20,7 +23,7 @@ namespace {
|
|||
* Helper function for the UTF-8 locale collations.
|
||||
*
|
||||
* @param aService
|
||||
* The Service that owns the nsICollation used by this collation.
|
||||
* The Service that owns the collator used by this collation.
|
||||
* @param aLen1
|
||||
* The number of bytes in aStr1.
|
||||
* @param aStr1
|
||||
|
@ -31,26 +34,26 @@ namespace {
|
|||
* @param aStr2
|
||||
* The string to be compared against aStr1 as provided by SQLite. It
|
||||
* must be a non-null-terminated char* buffer.
|
||||
* @param aComparisonStrength
|
||||
* The sorting strength, one of the nsICollation constants.
|
||||
* @param aSensitivity
|
||||
* The sorting sensitivity.
|
||||
* @return aStr1 - aStr2. That is, if aStr1 < aStr2, returns a negative number.
|
||||
* If aStr1 > aStr2, returns a positive number. If aStr1 == aStr2,
|
||||
* returns 0.
|
||||
*/
|
||||
int localeCollationHelper8(void* aService, int aLen1, const void* aStr1,
|
||||
int aLen2, const void* aStr2,
|
||||
int32_t aComparisonStrength) {
|
||||
Collator::Sensitivity aSensitivity) {
|
||||
NS_ConvertUTF8toUTF16 str1(static_cast<const char*>(aStr1), aLen1);
|
||||
NS_ConvertUTF8toUTF16 str2(static_cast<const char*>(aStr2), aLen2);
|
||||
Service* serv = static_cast<Service*>(aService);
|
||||
return serv->localeCompareStrings(str1, str2, aComparisonStrength);
|
||||
return serv->localeCompareStrings(str1, str2, aSensitivity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for the UTF-16 locale collations.
|
||||
*
|
||||
* @param aService
|
||||
* The Service that owns the nsICollation used by this collation.
|
||||
* The Service that owns the collator used by this collation.
|
||||
* @param aLen1
|
||||
* The number of bytes (not characters) in aStr1.
|
||||
* @param aStr1
|
||||
|
@ -61,15 +64,15 @@ int localeCollationHelper8(void* aService, int aLen1, const void* aStr1,
|
|||
* @param aStr2
|
||||
* The string to be compared against aStr1 as provided by SQLite. It
|
||||
* must be a non-null-terminated char16_t* buffer.
|
||||
* @param aComparisonStrength
|
||||
* The sorting strength, one of the nsICollation constants.
|
||||
* @param aSensitivity
|
||||
* The sorting sensitivity.
|
||||
* @return aStr1 - aStr2. That is, if aStr1 < aStr2, returns a negative number.
|
||||
* If aStr1 > aStr2, returns a positive number. If aStr1 == aStr2,
|
||||
* returns 0.
|
||||
*/
|
||||
int localeCollationHelper16(void* aService, int aLen1, const void* aStr1,
|
||||
int aLen2, const void* aStr2,
|
||||
int32_t aComparisonStrength) {
|
||||
Collator::Sensitivity aSensitivity) {
|
||||
const char16_t* buf1 = static_cast<const char16_t*>(aStr1);
|
||||
const char16_t* buf2 = static_cast<const char16_t*>(aStr2);
|
||||
|
||||
|
@ -80,7 +83,7 @@ int localeCollationHelper16(void* aService, int aLen1, const void* aStr1,
|
|||
nsDependentSubstring str1(buf1, buf1 + (aLen1 / sizeof(char16_t)));
|
||||
nsDependentSubstring str2(buf2, buf2 + (aLen2 / sizeof(char16_t)));
|
||||
Service* serv = static_cast<Service*>(aService);
|
||||
return serv->localeCompareStrings(str1, str2, aComparisonStrength);
|
||||
return serv->localeCompareStrings(str1, str2, aSensitivity);
|
||||
}
|
||||
|
||||
// This struct is used only by registerCollations below, but ISO C++98 forbids
|
||||
|
@ -127,53 +130,53 @@ int registerCollations(sqlite3* aDB, Service* aService) {
|
|||
int localeCollation8(void* aService, int aLen1, const void* aStr1, int aLen2,
|
||||
const void* aStr2) {
|
||||
return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2,
|
||||
nsICollation::kCollationCaseInSensitive);
|
||||
Collator::Sensitivity::Base);
|
||||
}
|
||||
|
||||
int localeCollationCaseSensitive8(void* aService, int aLen1, const void* aStr1,
|
||||
int aLen2, const void* aStr2) {
|
||||
return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2,
|
||||
nsICollation::kCollationAccentInsenstive);
|
||||
Collator::Sensitivity::Case);
|
||||
}
|
||||
|
||||
int localeCollationAccentSensitive8(void* aService, int aLen1,
|
||||
const void* aStr1, int aLen2,
|
||||
const void* aStr2) {
|
||||
return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2,
|
||||
nsICollation::kCollationCaseInsensitiveAscii);
|
||||
Collator::Sensitivity::Accent);
|
||||
}
|
||||
|
||||
int localeCollationCaseAccentSensitive8(void* aService, int aLen1,
|
||||
const void* aStr1, int aLen2,
|
||||
const void* aStr2) {
|
||||
return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2,
|
||||
nsICollation::kCollationCaseSensitive);
|
||||
Collator::Sensitivity::Variant);
|
||||
}
|
||||
|
||||
int localeCollation16(void* aService, int aLen1, const void* aStr1, int aLen2,
|
||||
const void* aStr2) {
|
||||
return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2,
|
||||
nsICollation::kCollationCaseInSensitive);
|
||||
Collator::Sensitivity::Base);
|
||||
}
|
||||
|
||||
int localeCollationCaseSensitive16(void* aService, int aLen1, const void* aStr1,
|
||||
int aLen2, const void* aStr2) {
|
||||
return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2,
|
||||
nsICollation::kCollationAccentInsenstive);
|
||||
Collator::Sensitivity::Case);
|
||||
}
|
||||
|
||||
int localeCollationAccentSensitive16(void* aService, int aLen1,
|
||||
const void* aStr1, int aLen2,
|
||||
const void* aStr2) {
|
||||
return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2,
|
||||
nsICollation::kCollationCaseInsensitiveAscii);
|
||||
Collator::Sensitivity::Accent);
|
||||
}
|
||||
|
||||
int localeCollationCaseAccentSensitive16(void* aService, int aLen1,
|
||||
const void* aStr1, int aLen2,
|
||||
const void* aStr2) {
|
||||
return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2,
|
||||
nsICollation::kCollationCaseSensitive);
|
||||
Collator::Sensitivity::Variant);
|
||||
}
|
||||
|
||||
} // namespace storage
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace storage {
|
|||
* @param aDB
|
||||
* The database we'll be registering the collations with.
|
||||
* @param aService
|
||||
* The Service that owns the nsICollation used by our collations.
|
||||
* The Service that owns the collator used by our collations.
|
||||
* @return the SQLite status code indicating success or failure.
|
||||
*/
|
||||
int registerCollations(sqlite3* aDB, Service* aService);
|
||||
|
@ -36,7 +36,7 @@ int registerCollations(sqlite3* aDB, Service* aService);
|
|||
* Comparison is case- and accent-insensitive. This is called by SQLite.
|
||||
*
|
||||
* @param aService
|
||||
* The Service that owns the nsICollation used by this collation.
|
||||
* The Service that owns the collator used by this collation.
|
||||
* @param aLen1
|
||||
* The number of bytes in aStr1.
|
||||
* @param aStr1
|
||||
|
@ -60,7 +60,7 @@ int localeCollation8(void* aService, int aLen1, const void* aStr1, int aLen2,
|
|||
* SQLite.
|
||||
*
|
||||
* @param aService
|
||||
* The Service that owns the nsICollation used by this collation.
|
||||
* The Service that owns the collator used by this collation.
|
||||
* @param aLen1
|
||||
* The number of bytes in aStr1.
|
||||
* @param aStr1
|
||||
|
@ -84,7 +84,7 @@ int localeCollationCaseSensitive8(void* aService, int aLen1, const void* aStr1,
|
|||
* SQLite.
|
||||
*
|
||||
* @param aService
|
||||
* The Service that owns the nsICollation used by this collation.
|
||||
* The Service that owns the collator used by this collation.
|
||||
* @param aLen1
|
||||
* The number of bytes in aStr1.
|
||||
* @param aStr1
|
||||
|
@ -108,7 +108,7 @@ int localeCollationAccentSensitive8(void* aService, int aLen1,
|
|||
* Comparison is case- and accent-sensitive. This is called by SQLite.
|
||||
*
|
||||
* @param aService
|
||||
* The Service that owns the nsICollation used by this collation.
|
||||
* The Service that owns the collator used by this collation.
|
||||
* @param aLen1
|
||||
* The number of bytes in aStr1.
|
||||
* @param aStr1
|
||||
|
@ -132,7 +132,7 @@ int localeCollationCaseAccentSensitive8(void* aService, int aLen1,
|
|||
* Comparison is case- and accent-insensitive. This is called by SQLite.
|
||||
*
|
||||
* @param aService
|
||||
* The Service that owns the nsICollation used by this collation.
|
||||
* The Service that owns the collator used by this collation.
|
||||
* @param aLen1
|
||||
* The number of bytes (not characters) in aStr1.
|
||||
* @param aStr1
|
||||
|
@ -156,7 +156,7 @@ int localeCollation16(void* aService, int aLen1, const void* aStr1, int aLen2,
|
|||
* SQLite.
|
||||
*
|
||||
* @param aService
|
||||
* The Service that owns the nsICollation used by this collation.
|
||||
* The Service that owns the collator used by this collation.
|
||||
* @param aLen1
|
||||
* The number of bytes (not characters) in aStr1.
|
||||
* @param aStr1
|
||||
|
@ -180,7 +180,7 @@ int localeCollationCaseSensitive16(void* aService, int aLen1, const void* aStr1,
|
|||
* SQLite.
|
||||
*
|
||||
* @param aService
|
||||
* The Service that owns the nsICollation used by this collation.
|
||||
* The Service that owns the collator used by this collation.
|
||||
* @param aLen1
|
||||
* The number of bytes (not characters) in aStr1.
|
||||
* @param aStr1
|
||||
|
@ -204,7 +204,7 @@ int localeCollationAccentSensitive16(void* aService, int aLen1,
|
|||
* Comparison is case- and accent-sensitive. This is called by SQLite.
|
||||
*
|
||||
* @param aService
|
||||
* The Service that owns the nsICollation used by this collation.
|
||||
* The Service that owns the collator used by this collation.
|
||||
* @param aLen1
|
||||
* The number of bytes (not characters) in aStr1.
|
||||
* @param aStr1
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include "mozIStorageCompletionCallback.h"
|
||||
#include "mozIStoragePendingStatement.h"
|
||||
#include "mozilla/StaticPrefs_storage.h"
|
||||
#include "mozilla/intl/Collator.h"
|
||||
#include "mozilla/intl/LocaleService.h"
|
||||
|
||||
#include "sqlite3.h"
|
||||
#include "mozilla/AutoSQLiteLifetime.h"
|
||||
|
@ -31,6 +33,8 @@
|
|||
# undef CompareString
|
||||
#endif
|
||||
|
||||
using mozilla::intl::Collator;
|
||||
|
||||
namespace mozilla {
|
||||
namespace storage {
|
||||
|
||||
|
@ -354,47 +358,58 @@ nsresult Service::initialize() {
|
|||
|
||||
int Service::localeCompareStrings(const nsAString& aStr1,
|
||||
const nsAString& aStr2,
|
||||
int32_t aComparisonStrength) {
|
||||
// The implementation of nsICollation.CompareString() is platform-dependent.
|
||||
// On Linux it's not thread-safe. It may not be on Windows and OS X either,
|
||||
// but it's more difficult to tell. We therefore synchronize this method.
|
||||
Collator::Sensitivity aSensitivity) {
|
||||
// The mozilla::intl::Collator is not thread safe, since the Collator::Options
|
||||
// can be changed.
|
||||
MutexAutoLock mutex(mMutex);
|
||||
|
||||
nsICollation* coll = getLocaleCollation();
|
||||
if (!coll) {
|
||||
Collator* collator = getCollator();
|
||||
if (!collator) {
|
||||
NS_ERROR("Storage service has no collation");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t res;
|
||||
nsresult rv = coll->CompareString(aComparisonStrength, aStr1, aStr2, &res);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("Collation compare string failed");
|
||||
return 0;
|
||||
if (aSensitivity != mLastSensitivity) {
|
||||
auto result =
|
||||
mCollator->SetOptions(Collator::Options{.sensitivity = aSensitivity});
|
||||
|
||||
if (result.isErr()) {
|
||||
NS_WARNING("Could not configure the mozilla::intl::Collation.");
|
||||
return 0;
|
||||
}
|
||||
mLastSensitivity = aSensitivity;
|
||||
}
|
||||
|
||||
return res;
|
||||
return collator->CompareStrings(aStr1, aStr2);
|
||||
}
|
||||
|
||||
nsICollation* Service::getLocaleCollation() {
|
||||
Collator* Service::getCollator() {
|
||||
mMutex.AssertCurrentThreadOwns();
|
||||
|
||||
if (mLocaleCollation) return mLocaleCollation;
|
||||
if (mCollator) {
|
||||
return mCollator.get();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsICollationFactory> collFact =
|
||||
do_CreateInstance(NS_COLLATIONFACTORY_CONTRACTID);
|
||||
if (!collFact) {
|
||||
NS_WARNING("Could not create collation factory");
|
||||
auto result = mozilla::intl::LocaleService::TryCreateComponent<Collator>();
|
||||
if (result.isErr()) {
|
||||
NS_WARNING("Could not create mozilla::intl::Collation.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsresult rv = collFact->CreateCollation(getter_AddRefs(mLocaleCollation));
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Could not create collation");
|
||||
mCollator = result.unwrap();
|
||||
|
||||
// Sort in a case-insensitive way, where "base" letters are considered
|
||||
// equal, e.g: a = á, a = A, a ≠ b.
|
||||
auto optResult = mCollator->SetOptions(
|
||||
Collator::Options{.sensitivity = Collator::Sensitivity::Base});
|
||||
|
||||
if (optResult.isErr()) {
|
||||
NS_WARNING("Could not configure the mozilla::intl::Collation.");
|
||||
mCollator = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return mLocaleCollation;
|
||||
return mCollator.get();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -8,17 +8,21 @@
|
|||
#define MOZSTORAGESERVICE_H
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsICollation.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsTArray.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/intl/Collator.h"
|
||||
|
||||
#include "mozIStorageService.h"
|
||||
|
||||
class nsIMemoryReporter;
|
||||
struct sqlite3_vfs;
|
||||
namespace mozilla::intl {
|
||||
class Collator;
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
namespace storage {
|
||||
|
@ -40,14 +44,14 @@ class Service : public mozIStorageService,
|
|||
* The string to be compared against aStr2.
|
||||
* @param aStr2
|
||||
* The string to be compared against aStr1.
|
||||
* @param aComparisonStrength
|
||||
* The sorting strength, one of the nsICollation constants.
|
||||
* @param aSensitivity
|
||||
* The sorting sensitivity.
|
||||
* @return aStr1 - aStr2. That is, if aStr1 < aStr2, returns a negative
|
||||
* number. If aStr1 > aStr2, returns a positive number. If
|
||||
* aStr1 == aStr2, returns 0.
|
||||
*/
|
||||
int localeCompareStrings(const nsAString& aStr1, const nsAString& aStr2,
|
||||
int32_t aComparisonStrength);
|
||||
mozilla::intl::Collator::Sensitivity aSensitivity);
|
||||
|
||||
static already_AddRefed<Service> getSingleton();
|
||||
|
||||
|
@ -147,28 +151,30 @@ class Service : public mozIStorageService,
|
|||
void minimizeMemory();
|
||||
|
||||
/**
|
||||
* Lazily creates and returns a collation created from the application's
|
||||
* Lazily creates and returns a collator created from the application's
|
||||
* locale that all statements of all Connections of this Service may use.
|
||||
* Since the collation's lifetime is that of the Service and no statement may
|
||||
* Since the collator's lifetime is that of the Service and no statement may
|
||||
* execute outside the lifetime of the Service, this method returns a raw
|
||||
* pointer.
|
||||
*/
|
||||
nsICollation* getLocaleCollation();
|
||||
mozilla::intl::Collator* getCollator();
|
||||
|
||||
/**
|
||||
* Lazily created collation that all statements of all Connections of this
|
||||
* Service may use. The collation is created from the application's locale.
|
||||
* Lazily created collator that all statements of all Connections of this
|
||||
* Service may use. The collator is created from the application's locale.
|
||||
*
|
||||
* @note Collation implementations are platform-dependent and in general not
|
||||
* thread-safe. Access to this collation should be synchronized.
|
||||
* @note The collator is not thread-safe since the options can be changed
|
||||
* between calls. Access should be synchronized.
|
||||
*/
|
||||
nsCOMPtr<nsICollation> mLocaleCollation;
|
||||
mozilla::UniquePtr<mozilla::intl::Collator> mCollator = nullptr;
|
||||
|
||||
nsCOMPtr<nsIFile> mProfileStorageFile;
|
||||
|
||||
nsCOMPtr<nsIMemoryReporter> mStorageSQLiteReporter;
|
||||
|
||||
static Service* gService;
|
||||
|
||||
mozilla::intl::Collator::Sensitivity mLastSensitivity;
|
||||
};
|
||||
|
||||
} // namespace storage
|
||||
|
|
Загрузка…
Ссылка в новой задаче