diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2021-07-30 13:45:46 -0700 |
---|---|---|
committer | Edward Welbourne <edward.welbourne@qt.io> | 2021-11-01 22:30:23 +0200 |
commit | a9d8794cf0be617d9eedbf9bb0d6d5401735d6f2 (patch) | |
tree | 16fea80f32bebf3f815f0122371738403d9f015c | |
parent | 25d807f6292e9918ccdbe06cf7f590f60ecae457 (diff) |
QCollator: add public, static functions to do comparisons
Collation with the default QCollator object (no numeric, punctuation or
case sensitivity changes) is a common-place occurrence, so add two
functions to do this work.
It's also what QString::localeAwareCompare() calls.
The test ends up testing that default, static collator updates after the
default QLocale changes too.
Task-number: QTBUG-95050
Change-Id: I7e0b82c2d2fe464082d8fffd1696ac77f32840b2
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
-rw-r--r-- | src/corelib/text/qcollator.cpp | 51 | ||||
-rw-r--r-- | src/corelib/text/qcollator.h | 3 | ||||
-rw-r--r-- | src/corelib/text/qstring.cpp | 26 | ||||
-rw-r--r-- | tests/auto/corelib/text/qcollator/tst_qcollator.cpp | 15 |
4 files changed, 70 insertions, 25 deletions
diff --git a/src/corelib/text/qcollator.cpp b/src/corelib/text/qcollator.cpp index 425bfc82ff..8bffae83da 100644 --- a/src/corelib/text/qcollator.cpp +++ b/src/corelib/text/qcollator.cpp @@ -43,9 +43,33 @@ #include "qstring.h" #include "qdebug.h" +#include "qlocale_p.h" +#include "qthreadstorage.h" QT_BEGIN_NAMESPACE +namespace { +struct GenerationalCollator +{ + QCollator theCollator; + int generation = QLocalePrivate::s_generation.loadRelaxed(); +public: + GenerationalCollator() = default; + GenerationalCollator(const QCollator ©) : theCollator(copy) {} + QCollator &collator() + { + int currentGeneration = QLocalePrivate::s_generation.loadRelaxed(); + if (Q_UNLIKELY(generation != currentGeneration)) { + // reinitialize the collator + generation = currentGeneration; + theCollator = QCollator(); + } + return theCollator; + } +}; +} +Q_GLOBAL_STATIC(QThreadStorage<GenerationalCollator>, defaultCollator) + /*! \class QCollator \inmodule QtCore @@ -345,6 +369,33 @@ bool QCollator::ignorePunctuation() const #endif // QT_STRINGVIEW_LEVEL < 2 /*! + \since 6.3 + + Compares the strings \a s1 and \a s2, returning their sorting order. This + function performs the same operation as compare() on a default-constructed + QCollator object. + + \sa compare(), defaultSortKey() +*/ +int QCollator::defaultCompare(QStringView s1, QStringView s2) +{ + return defaultCollator->localData().collator().compare(s1, s2); +} + +/*! + \since 6.3 + + Returns the sort key for the string \a key. This function performs the same + operation as sortKey() on a default-constructed QCollator object. + + \sa sortKey(), defaultCompare() +*/ +QCollatorSortKey QCollator::defaultSortKey(QStringView key) +{ + return defaultCollator->localData().collator().sortKey(key.toString()); +} + +/*! \fn QCollatorSortKey QCollator::sortKey(const QString &string) const Returns a sortKey for \a string. diff --git a/src/corelib/text/qcollator.h b/src/corelib/text/qcollator.h index 2063dfb4a1..ddfbacfd19 100644 --- a/src/corelib/text/qcollator.h +++ b/src/corelib/text/qcollator.h @@ -117,6 +117,9 @@ public: QCollatorSortKey sortKey(const QString &string) const; + static int defaultCompare(QStringView s1, QStringView s2); + static QCollatorSortKey defaultSortKey(QStringView key); + private: QCollatorPrivate *d; diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp index 5bef030e42..d1d4199fc5 100644 --- a/src/corelib/text/qstring.cpp +++ b/src/corelib/text/qstring.cpp @@ -6214,28 +6214,6 @@ int QString::localeAwareCompare(const QString &other) const return localeAwareCompare_helper(constData(), length(), other.constData(), other.length()); } -#if QT_CONFIG(icu) -namespace { -class GenerationalCollator -{ - QCollator theCollator; - int generation = QLocalePrivate::s_generation.loadRelaxed(); -public: - QCollator &collator() - { - int currentGeneration = QLocalePrivate::s_generation.loadRelaxed(); - if (Q_UNLIKELY(generation != currentGeneration)) { - // reinitialize the collator - generation = currentGeneration; - theCollator = QCollator(); - } - return theCollator; - } -}; -} -Q_GLOBAL_STATIC(QThreadStorage<GenerationalCollator>, defaultCollator) -#endif - /*! \internal \since 4.5 @@ -6254,9 +6232,7 @@ int QString::localeAwareCompare_helper(const QChar *data1, qsizetype length1, Qt::CaseSensitive); #if QT_CONFIG(icu) - if (!defaultCollator()->hasLocalData()) - defaultCollator()->setLocalData(GenerationalCollator()); - return defaultCollator()->localData().collator().compare(data1, length1, data2, length2); + return QCollator::defaultCompare(QStringView(data1, length1), QStringView(data2, length2)); #else const QString lhs = QString::fromRawData(data1, length1).normalized(QString::NormalizationForm_C); const QString rhs = QString::fromRawData(data2, length2).normalized(QString::NormalizationForm_C); diff --git a/tests/auto/corelib/text/qcollator/tst_qcollator.cpp b/tests/auto/corelib/text/qcollator/tst_qcollator.cpp index ce1844f345..7c9ed76f77 100644 --- a/tests/auto/corelib/text/qcollator/tst_qcollator.cpp +++ b/tests/auto/corelib/text/qcollator/tst_qcollator.cpp @@ -31,6 +31,7 @@ #include <qlocale.h> #include <qcollator.h> #include <private/qglobal_p.h> +#include <QScopeGuard> #include <cstring> @@ -276,6 +277,13 @@ void tst_QCollator::compare() QFETCH(int, punctuationResult); QCollator collator((QLocale(locale))); + + // AFTER the QCollator initialization + auto localechanger = qScopeGuard([original = QLocale()] { + QLocale::setDefault(original); // reset back to what it was + }); + QLocale::setDefault(QLocale(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; @@ -310,10 +318,17 @@ void tst_QCollator::compare() // NOTE: currently QCollatorSortKey::compare is not working // properly without icu: see QTBUG-88704 for details QCOMPARE(asSign(collator.compare(s1, s2)), result); + if (!numericMode) + QCOMPARE(asSign(QCollator::defaultCompare(s1, s2)), result); #if QT_CONFIG(icu) auto key1 = collator.sortKey(s1); auto key2 = collator.sortKey(s2); QCOMPARE(asSign(key1.compare(key2)), keyCompareResult); + + key1 = QCollator::defaultSortKey(s1); + key2 = QCollator::defaultSortKey(s2); + if (!numericMode) + QCOMPARE(asSign(key1.compare(key2)), keyCompareResult); #endif collator.setCaseSensitivity(Qt::CaseInsensitive); QCOMPARE(asSign(collator.compare(s1, s2)), caseInsensitiveResult); |