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>
This commit is contained in:
parent
25d807f629
commit
a9d8794cf0
@ -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
|
||||
@ -344,6 +368,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
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user