summaryrefslogtreecommitdiffstats
path: root/src/corelib/text/qcollator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/text/qcollator.cpp')
-rw-r--r--src/corelib/text/qcollator.cpp319
1 files changed, 183 insertions, 136 deletions
diff --git a/src/corelib/text/qcollator.cpp b/src/corelib/text/qcollator.cpp
index 4bef356044..1f7e7459e7 100644
--- a/src/corelib/text/qcollator.cpp
+++ b/src/corelib/text/qcollator.cpp
@@ -1,50 +1,39 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2013 Aleix Pol Gonzalez <aleixpol@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2013 Aleix Pol Gonzalez <aleixpol@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcollator_p.h"
#include "qstringlist.h"
#include "qstring.h"
#include "qdebug.h"
+#include "qlocale_p.h"
+#include "qthreadstorage.h"
QT_BEGIN_NAMESPACE
+QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QCollatorSortKeyPrivate)
+
+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
@@ -58,35 +47,60 @@ QT_BEGIN_NAMESPACE
\ingroup string-processing
\ingroup shared
- QCollator is initialized with a QLocale and an optional collation strategy.
- It tries to initialize the collator with the specified values. The collator
- can then be used to compare and sort strings in a locale dependent fashion.
+ QCollator is initialized with a QLocale. It can then be used to compare and
+ sort strings by using the ordering appropriate for that locale.
+
+ A QCollator object can be used together with template-based sorting
+ algorithms, such as std::sort(), to sort a list with QString entries.
+
+ \snippet code/src_corelib_text_qcollator.cpp 0
+
+ In addition to the locale, several optional flags can be set that influence
+ the result of the collation.
+
+ \section1 POSIX fallback implementation
+
+ On Unix systems, Qt is normally compiled to use ICU (except for \macos,
+ where Qt defaults to using an equivalent Apple API). However, if ICU was
+ not available at compile time or explicitly disabled, Qt will use a
+ fallback backend that uses the POSIX API only. This backend has several
+ limitations:
- A QCollator object can be used together with template based sorting
- algorithms such as std::sort to sort a list of QStrings.
+ \list
+ \li Only the QLocale::c() and QLocale::system() locales are supported.
+ Consult the POSIX and C Standard Library manuals for the
+ \c{<locale.h>} header for more information on the system locale.
+ \li caseSensitivity() is not supported: only case-sensitive collation
+ can be performed.
+ \li numericMode() and ignorePunctuation() are not supported.
+ \endlist
- In addition to the locale and collation strategy, several optional flags can
- be set that influence the result of the collation.
+ The use of any of the unsupported options will cause a warning to be
+ printed to the application's output.
*/
/*!
\since 5.13
- Constructs a QCollator using the system's default collation locale.
+ Constructs a QCollator using the default locale's collation locale.
- \sa setLocale(), QLocale::collation()
+ The system locale, when used as default locale, may have a collation locale
+ other than itself (e.g. on Unix, if LC_COLLATE is set differently to LANG in
+ the environment). All other locales are their own collation locales.
+
+ \sa setLocale(), QLocale::collation(), QLocale::setDefault()
*/
QCollator::QCollator()
- : d(new QCollatorPrivate(QLocale::system().collation()))
+ : d(new QCollatorPrivate(QLocale().collation()))
{
d->init();
}
/*!
- Constructs a QCollator from \a locale.
+ Constructs a QCollator using the given \a locale.
\sa setLocale()
- */
+*/
QCollator::QCollator(const QLocale &locale)
: d(new QCollatorPrivate(locale))
{
@@ -94,21 +108,20 @@ QCollator::QCollator(const QLocale &locale)
/*!
Creates a copy of \a other.
- */
+*/
QCollator::QCollator(const QCollator &other)
: d(other.d)
{
if (d) {
// Ensure clean, lest both copies try to init() at the same time:
- if (d->dirty)
- d->init();
+ d->ensureInitialized();
d->ref.ref();
}
}
/*!
- Destroys the collator.
- */
+ Destroys this collator.
+*/
QCollator::~QCollator()
{
if (d && !d->ref.deref())
@@ -117,7 +130,7 @@ QCollator::~QCollator()
/*!
Assigns \a other to this collator.
- */
+*/
QCollator &QCollator::operator=(const QCollator &other)
{
if (this != &other) {
@@ -126,8 +139,7 @@ QCollator &QCollator::operator=(const QCollator &other)
d = other.d;
if (d) {
// Ensure clean, lest both copies try to init() at the same time:
- if (d->dirty)
- d->init();
+ d->ensureInitialized();
d->ref.ref();
}
}
@@ -139,19 +151,19 @@ QCollator &QCollator::operator=(const QCollator &other)
Move constructor. Moves from \a other into this collator.
- Note that a moved-from QCollator can only be destroyed or assigned to.
- The effect of calling other functions than the destructor or one of the
- assignment operators is undefined.
+//! [partially-formed]
+ \note The moved-from object \a other is placed in a partially-formed state,
+ in which the only valid operations are destruction and assignment of a new
+ value.
+//! [partially-formed]
*/
/*!
\fn QCollator & QCollator::operator=(QCollator && other)
- Move-assigns from \a other to this collator.
+ Move-assigns \a other to this QCollator instance.
- Note that a moved-from QCollator can only be destroyed or assigned to.
- The effect of calling other functions than the destructor or one of the
- assignment operators is undefined.
+ \include qcollator.cpp partially-formed
*/
/*!
@@ -163,7 +175,7 @@ QCollator &QCollator::operator=(const QCollator &other)
/*!
\internal
- */
+*/
void QCollator::detach()
{
if (d->ref.loadRelaxed() != 1) {
@@ -178,7 +190,9 @@ void QCollator::detach()
/*!
Sets the locale of the collator to \a locale.
- */
+
+ \sa locale()
+*/
void QCollator::setLocale(const QLocale &locale)
{
if (locale == d->locale)
@@ -190,19 +204,22 @@ void QCollator::setLocale(const QLocale &locale)
/*!
Returns the locale of the collator.
- */
+
+ Unless supplied to the constructor or by calling setLocale(), the system's
+ default collation locale is used.
+
+ \sa setLocale(), QLocale::collation()
+*/
QLocale QCollator::locale() const
{
return d->locale;
}
/*!
- \fn void QCollator::setCaseSensitivity(Qt::CaseSensitivity sensitivity)
-
- Sets the case \a sensitivity of the collator.
+ Sets the case-sensitivity of the collator to \a cs.
\sa caseSensitivity()
- */
+*/
void QCollator::setCaseSensitivity(Qt::CaseSensitivity cs)
{
if (d->caseSensitivity == cs)
@@ -213,29 +230,27 @@ void QCollator::setCaseSensitivity(Qt::CaseSensitivity cs)
}
/*!
- \fn Qt::CaseSensitivity QCollator::caseSensitivity() const
-
Returns case sensitivity of the collator.
+ This defaults to case-sensitive until set.
+
+ \note In the C locale, when case-sensitive, all lower-case letters sort
+ after all upper-case letters, where most locales sort each lower-case letter
+ either immediately before or immediately after its upper-case partner. Thus
+ "Zap" sorts before "ape" in the C locale but after in most others.
+
\sa setCaseSensitivity()
- */
+*/
Qt::CaseSensitivity QCollator::caseSensitivity() const
{
return d->caseSensitivity;
}
/*!
- \fn void QCollator::setNumericMode(bool on)
-
- Enables numeric sorting mode when \a on is set to true.
-
- This will enable proper sorting of numeric digits, so that e.g. 100 sorts
- after 99.
-
- By default this mode is off.
+ Enables numeric sorting mode when \a on is \c true.
\sa numericMode()
- */
+*/
void QCollator::setNumericMode(bool on)
{
if (d->numericMode == on)
@@ -246,30 +261,25 @@ void QCollator::setNumericMode(bool on)
}
/*!
- \fn bool QCollator::numericMode() const
+ Returns \c true if numeric sorting is enabled, \c false otherwise.
- Returns \c true if numeric sorting is enabled, false otherwise.
+ When \c true, numerals are recognized as numbers and sorted in arithmetic
+ order; for example, 100 sortes after 99. When \c false, numbers are sorted
+ in lexical order, so that 100 sorts before 99 (because 1 is before 9). By
+ default, this option is disabled.
\sa setNumericMode()
- */
+*/
bool QCollator::numericMode() const
{
return d->numericMode;
}
/*!
- \fn void QCollator::setIgnorePunctuation(bool on)
-
- If \a on is set to true, punctuation characters and symbols are ignored when
- determining sort order.
-
- The default is locale dependent.
-
- \note This method is not currently supported if Qt is configured to not use
- ICU on Linux.
+ Ignores punctuation and symbols if \a on is \c true, attends to them if \c false.
\sa ignorePunctuation()
- */
+*/
void QCollator::setIgnorePunctuation(bool on)
{
if (d->ignorePunctuation == on)
@@ -280,13 +290,13 @@ void QCollator::setIgnorePunctuation(bool on)
}
/*!
- \fn bool QCollator::ignorePunctuation() const
+ Returns whether punctuation and symbols are ignored when collating.
- Returns \c true if punctuation characters and symbols are ignored when
- determining sort order.
+ When \c true, strings are compared as if all punctuation and symbols were
+ removed from each string.
\sa setIgnorePunctuation()
- */
+*/
bool QCollator::ignorePunctuation() const
{
return d->ignorePunctuation;
@@ -295,7 +305,11 @@ bool QCollator::ignorePunctuation() const
/*!
\since 5.13
\fn bool QCollator::operator()(QStringView s1, QStringView s2) const
- \internal
+
+ A QCollator can be used as the comparison function of a sorting algorithm.
+ It returns \c true if \a s1 sorts before \a s2, otherwise \c false.
+
+ \sa compare()
*/
/*!
@@ -304,42 +318,64 @@ bool QCollator::ignorePunctuation() const
Compares \a s1 with \a s2.
- Returns an integer less than, equal to, or greater than zero depending on
- whether \a s1 sorts before, with or after \a s2.
+ Returns a negative integer if \a s1 is less than \a s2, a positive integer
+ if it is greater than \a s2, and zero if they are equal.
*/
-#if QT_STRINGVIEW_LEVEL < 2
+
/*!
\fn bool QCollator::operator()(const QString &s1, const QString &s2) const
- \internal
+ \overload
+ \since 5.2
*/
/*!
+ \fn int QCollator::compare(const QString &s1, const QString &s2) const
\overload
+ \since 5.2
+*/
- Compares \a s1 with \a s2.
+/*!
+ \fn int QCollator::compare(const QChar *s1, qsizetype len1, const QChar *s2, qsizetype len2) const
+ \overload
+ \since 5.2
- Returns an integer less than, equal to, or greater than zero depending on
- whether \a s1 sorts before, with or after \a s2.
+ Compares \a s1 with \a s2. \a len1 and \a len2 specify the lengths of the
+ QChar arrays pointed to by \a s1 and \a s2.
+
+ Returns a negative integer if \a s1 is less than \a s2, a positive integer
+ if it is greater than \a s2, and zero if they are equal.
+
+
+ \note In Qt versions prior to 6.4, the length arguments were of type
+ \c{int}, not \c{qsizetype}.
*/
-int QCollator::compare(const QString &s1, const QString &s2) const
+
+/*!
+ \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 compare(QStringView(s1), QStringView(s2));
+ return defaultCollator->localData().collator().compare(s1, s2);
}
/*!
- \overload
+ \since 6.3
- Compares \a s1 with \a s2. \a len1 and \a len2 specify the lengths of the
- QChar arrays pointed to by \a s1 and \a s2.
+ Returns the sort key for the string \a key. This function performs the same
+ operation as sortKey() on a default-constructed QCollator object.
- Returns an integer less than, equal to, or greater than zero depending on
- whether \a s1 sorts before, with or after \a s2.
+ \sa sortKey(), defaultCompare()
*/
-int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) const
+QCollatorSortKey QCollator::defaultSortKey(QStringView key)
{
- return compare(QStringView(s1, len1), QStringView(s2, len2));
+ return defaultCollator->localData().collator().sortKey(key.toString());
}
-#endif // QT_STRINGVIEW_LEVEL < 2
/*!
\fn QCollatorSortKey QCollator::sortKey(const QString &string) const
@@ -352,7 +388,7 @@ int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) con
keys for each string and then sort using the keys.
\note Not supported with the C (a.k.a. POSIX) locale on Darwin.
- */
+*/
/*!
\class QCollatorSortKey
@@ -369,12 +405,12 @@ int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) con
\ingroup string-processing
\ingroup shared
- \sa QCollator, QCollator::sortKey()
+ \sa QCollator, QCollator::sortKey(), compare()
*/
/*!
\internal
- */
+*/
QCollatorSortKey::QCollatorSortKey(QCollatorSortKeyPrivate *d)
: d(d)
{
@@ -389,15 +425,23 @@ QCollatorSortKey::QCollatorSortKey(const QCollatorSortKey &other)
}
/*!
+ \since 6.8
+ \fn QCollatorSortKey::QCollatorSortKey(QCollatorSortKey &&other)
+ Move-constructs a new QCollatorSortKey from \a other.
+
+ \include qcollator.cpp partially-formed
+*/
+
+/*!
Destroys the collator key.
- */
+*/
QCollatorSortKey::~QCollatorSortKey()
{
}
/*!
Assigns \a other to this collator key.
- */
+*/
QCollatorSortKey& QCollatorSortKey::operator=(const QCollatorSortKey &other)
{
if (this != &other) {
@@ -409,18 +453,20 @@ QCollatorSortKey& QCollatorSortKey::operator=(const QCollatorSortKey &other)
/*!
\fn QCollatorSortKey &QCollatorSortKey::operator=(QCollatorSortKey && other)
- Move-assigns \a other to this collator key.
+ Move-assigns \a other to this QCollatorSortKey instance.
+
+ \include qcollator.cpp partially-formed
*/
/*!
- \fn bool operator<(const QCollatorSortKey &lhs, const QCollatorSortKey &rhs)
- \relates QCollatorSortKey
+ \fn bool QCollatorSortKey::operator<(const QCollatorSortKey &lhs, const QCollatorSortKey &rhs)
- According to the QCollator that created the keys, returns \c true if \a lhs
- should be sorted before \a rhs; otherwise returns \c false.
+ Both keys must have been created by the same QCollator's sortKey(). Returns
+ \c true if \a lhs should be sorted before \a rhs, according to the QCollator
+ that created them; otherwise returns \c false.
\sa QCollatorSortKey::compare()
- */
+*/
/*!
\fn void QCollatorSortKey::swap(QCollatorSortKey & other)
@@ -431,13 +477,14 @@ QCollatorSortKey& QCollatorSortKey::operator=(const QCollatorSortKey &other)
/*!
\fn int QCollatorSortKey::compare(const QCollatorSortKey &otherKey) const
- Compares this key to \a otherKey.
+ Compares this key to \a otherKey, which must have been created by the same
+ QCollator's sortKey() as this key. The comparison is performed in accordance
+ with that QCollator's sort order.
- Returns a negative value if the key is less than \a otherKey, 0 if the key
- is equal to \a otherKey or a positive value if the key is greater than \a
- otherKey.
+ Returns a negative value if this key sorts before \a otherKey, 0 if the two
+ keys are equal or a positive value if this key sorts after \a otherKey.
\sa operator<()
- */
+*/
QT_END_NAMESPACE