summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2021-07-30 13:45:46 -0700
committerEdward Welbourne <edward.welbourne@qt.io>2021-11-01 22:30:23 +0200
commita9d8794cf0be617d9eedbf9bb0d6d5401735d6f2 (patch)
tree16fea80f32bebf3f815f0122371738403d9f015c
parent25d807f6292e9918ccdbe06cf7f590f60ecae457 (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.cpp51
-rw-r--r--src/corelib/text/qcollator.h3
-rw-r--r--src/corelib/text/qstring.cpp26
-rw-r--r--tests/auto/corelib/text/qcollator/tst_qcollator.cpp15
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 &copy) : 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);