diff options
author | Edward Welbourne <edward.welbourne@qt.io> | 2018-10-02 19:02:29 +0200 |
---|---|---|
committer | Edward Welbourne <edward.welbourne@qt.io> | 2018-12-11 19:05:07 +0000 |
commit | ab448f731ecd8437c7c5c8b96a0e7f419ec3a7ca (patch) | |
tree | fd92aef03d376177364253beddd3e74ce7ad2715 /src/corelib/tools/qcollator_posix.cpp | |
parent | 63b0eb3a89049f3a9166a29e8c8275d77323ec52 (diff) |
Handle QCollator with locale C by delegating to QString
Previously, the C locale was treated as English because each back-end
takes the locale's bcp47Name(), which maps C to en. However, the C
locale has its own rules; which QString helpfully implements; so we
can delegate to it in this case. Extended this to sort keys, where
possible. Clean up existing implementations in the process.
Extended tst_QCollator::compare() with some cases to check this. That
required wrapping the test's calls to collator.compare() in a sign
canonicalizer, since it can return any -ve for < or +ve for >, not
just -1 and +1 for these cases (and it'd be rash to hard-code specific
negative and positive values, as they may vary between backends).
[ChangeLog][QtCore][QCollator] Added support for collation in the C
locale, albeit this is only well-defined for ASCII. Collation sort
keys remain unsupported on Darwin.
Fixes: QTBUG-58621
Change-Id: I327010d90f09bd1b1816f5590cb124e3d423e61d
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/tools/qcollator_posix.cpp')
-rw-r--r-- | src/corelib/tools/qcollator_posix.cpp | 41 |
1 files changed, 23 insertions, 18 deletions
diff --git a/src/corelib/tools/qcollator_posix.cpp b/src/corelib/tools/qcollator_posix.cpp index 42413a4a82..81f97a02e1 100644 --- a/src/corelib/tools/qcollator_posix.cpp +++ b/src/corelib/tools/qcollator_posix.cpp @@ -48,10 +48,12 @@ QT_BEGIN_NAMESPACE void QCollatorPrivate::init() { - if (locale != QLocale()) - qWarning("Only default locale supported with the posix collation implementation"); - if (caseSensitivity != Qt::CaseSensitive) - qWarning("Case insensitive sorting unsupported in the posix collation implementation"); + if (!isC()) { + if (locale != QLocale()) + qWarning("Only C and default locale supported with the posix collation implementation"); + if (caseSensitivity != Qt::CaseSensitive) + qWarning("Case insensitive sorting unsupported in the posix collation implementation"); + } if (numericMode) qWarning("Numeric mode unsupported in the posix collation implementation"); if (ignorePunctuation) @@ -73,14 +75,16 @@ static void stringToWCharArray(QVarLengthArray<wchar_t> &ret, const QString &str int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) const { - QVarLengthArray<wchar_t> array1, array2; - stringToWCharArray(array1, QString(s1, len1)); - stringToWCharArray(array2, QString(s2, len2)); - return std::wcscoll(array1.constData(), array2.constData()); + return compare(QString::fromRawData(s1, len1), QString::fromRawData(s2, len2)); } int QCollator::compare(const QString &s1, const QString &s2) const { + if (d->isC()) + return s1.compare(s2, caseSensitivity()); + if (d->dirty) + d->init(); + QVarLengthArray<wchar_t> array1, array2; stringToWCharArray(array1, s1); stringToWCharArray(array2, s2); @@ -89,10 +93,7 @@ int QCollator::compare(const QString &s1, const QString &s2) const int QCollator::compare(const QStringRef &s1, const QStringRef &s2) const { - if (d->dirty) - d->init(); - - return compare(s1.constData(), s1.size(), s2.constData(), s2.size()); + return compare(s1.toString(), s2.toString()); } QCollatorSortKey QCollator::sortKey(const QString &string) const @@ -102,14 +103,18 @@ QCollatorSortKey QCollator::sortKey(const QString &string) const QVarLengthArray<wchar_t> original; stringToWCharArray(original, string); - QVector<wchar_t> result(string.size()); - size_t size = std::wcsxfrm(result.data(), original.constData(), string.size()); - if (size > uint(result.size())) { + QVector<wchar_t> result(original.size()); + if (d->isC()) { + std::copy(original.cbegin(), original.cend(), result.begin()); + } else { + size_t size = std::wcsxfrm(result.data(), original.constData(), string.size()); + if (size > uint(result.size())) { + result.resize(size+1); + size = std::wcsxfrm(result.data(), original.constData(), string.size()); + } result.resize(size+1); - size = std::wcsxfrm(result.data(), original.constData(), string.size()); + result[size] = 0; } - result.resize(size+1); - result[size] = 0; return QCollatorSortKey(new QCollatorSortKeyPrivate(std::move(result))); } |