From ab448f731ecd8437c7c5c8b96a0e7f419ec3a7ca Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 2 Oct 2018 19:02:29 +0200 Subject: 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 --- tests/auto/corelib/tools/qcollator/tst_qcollator.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'tests/auto/corelib') diff --git a/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp b/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp index 2d65d3433f..72f88a235d 100644 --- a/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp +++ b/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp @@ -93,7 +93,7 @@ void tst_QCollator::compare_data() QTest::addColumn("caseInsensitiveResult"); QTest::addColumn("numericMode"); QTest::addColumn("ignorePunctuation"); - QTest::addColumn("punctuationResult"); + QTest::addColumn("punctuationResult"); // Test ignores punctuation *and case* /* It's hard to test English, because it's treated differently @@ -169,8 +169,12 @@ void tst_QCollator::compare_data() QTest::newRow("french6") << QString("fr_FR") << QString("Test 9") << QString("Test_19") << -1 << -1 << true << true << -1; QTest::newRow("french7") << QString("fr_FR") << QString("test_19") << QString("test 19") << 1 << 1 << true << false << 1; QTest::newRow("french8") << QString("fr_FR") << QString("test.19") << QString("test,19") << 1 << 1 << true << true << 0; -} + // C locale: case sensitive [A-Z] < [a-z] but case insensitive [Aa] < [Bb] <...< [Zz] + const QString C = QStringLiteral("C"); + QTest::newRow("C:ABBA:AaaA") << C << QStringLiteral("ABBA") << QStringLiteral("AaaA") << -1 << 1 << false << false << 1; + QTest::newRow("C:AZa:aAZ") << C << QStringLiteral("AZa") << QStringLiteral("aAZ") << -1 << 1 << false << false << 1; +} void tst_QCollator::compare() { @@ -184,6 +188,10 @@ void tst_QCollator::compare() QFETCH(int, punctuationResult); QCollator collator(locale); + // Need to canonicalize sign to -1, 0 or 1, as .compare() can produce any -ve for <, any +ve for >. + auto asSign = [](int compared) { + return compared < 0 ? -1 : compared > 0 ? 1 : 0; + }; #if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) if (collator.locale() != QLocale()) @@ -193,12 +201,12 @@ void tst_QCollator::compare() if (numericMode) collator.setNumericMode(true); - QCOMPARE(collator.compare(s1, s2), result); + QCOMPARE(asSign(collator.compare(s1, s2)), result); collator.setCaseSensitivity(Qt::CaseInsensitive); - QCOMPARE(collator.compare(s1, s2), caseInsensitiveResult); + QCOMPARE(asSign(collator.compare(s1, s2)), caseInsensitiveResult); #if !QT_CONFIG(iconv) collator.setIgnorePunctuation(ignorePunctuation); - QCOMPARE(collator.compare(s1, s2), punctuationResult); + QCOMPARE(asSign(collator.compare(s1, s2)), punctuationResult); #endif } -- cgit v1.2.3