Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qcollator.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// Copyright (C) 2013 Aleix Pol Gonzalez <aleixpol@kde.org>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include "qcollator_p.h"
6#include "qstringlist.h"
7#include "qstring.h"
8
9#include "qdebug.h"
10#include "qlocale_p.h"
11#include "qthreadstorage.h"
12
14QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QCollatorSortKeyPrivate)
15
16namespace {
18{
20 int generation = QLocalePrivate::s_generation.loadRelaxed();
21public:
23 GenerationalCollator(const QCollator &copy) : theCollator(copy) {}
25 {
26 int currentGeneration = QLocalePrivate::s_generation.loadRelaxed();
27 if (Q_UNLIKELY(generation != currentGeneration)) {
28 // reinitialize the collator
29 generation = currentGeneration;
30 theCollator = QCollator();
31 }
32 return theCollator;
33 }
34};
35}
36Q_GLOBAL_STATIC(QThreadStorage<GenerationalCollator>, defaultCollator)
37
38/*!
39 \class QCollator
40 \inmodule QtCore
41 \brief The QCollator class compares strings according to a localized collation algorithm.
42
43 \since 5.2
44
45 \reentrant
46 \ingroup i18n
47 \ingroup string-processing
48 \ingroup shared
49
50 QCollator is initialized with a QLocale. It can then be used to compare and
51 sort strings by using the ordering appropriate for that locale.
52
53 A QCollator object can be used together with template-based sorting
54 algorithms, such as std::sort(), to sort a list with QString entries.
55
56 \snippet code/src_corelib_text_qcollator.cpp 0
57
58 In addition to the locale, several optional flags can be set that influence
59 the result of the collation.
60
61 \section1 POSIX fallback implementation
62
63 On Unix systems, Qt is normally compiled to use ICU (except for \macos,
64 where Qt defaults to using an equivalent Apple API). However, if ICU was
65 not available at compile time or explicitly disabled, Qt will use a
66 fallback backend that uses the POSIX API only. This backend has several
67 limitations:
68
69 \list
70 \li Only the QLocale::c() and QLocale::system() locales are supported.
71 Consult the POSIX and C Standard Library manuals for the
72 \c{<locale.h>} header for more information on the system locale.
73 \li caseSensitivity() is not supported: only case-sensitive collation
74 can be performed.
75 \li numericMode() and ignorePunctuation() are not supported.
76 \endlist
77
78 The use of any of the unsupported options will cause a warning to be
79 printed to the application's output.
80*/
81
82/*!
83 \since 5.13
84
85 Constructs a QCollator using the default locale's collation locale.
86
87 The system locale, when used as default locale, may have a collation locale
88 other than itself (e.g. on Unix, if LC_COLLATE is set differently to LANG in
89 the environment). All other locales are their own collation locales.
90
91 \sa setLocale(), QLocale::collation(), QLocale::setDefault()
92*/
93QCollator::QCollator()
94 : d(new QCollatorPrivate(QLocale().collation()))
95{
96 d->init();
97}
98
99/*!
100 Constructs a QCollator using the given \a locale.
101
102 \sa setLocale()
103*/
104QCollator::QCollator(const QLocale &locale)
105 : d(new QCollatorPrivate(locale))
106{
107}
108
109/*!
110 Creates a copy of \a other.
111*/
112QCollator::QCollator(const QCollator &other)
113 : d(other.d)
114{
115 if (d) {
116 // Ensure clean, lest both copies try to init() at the same time:
117 d->ensureInitialized();
118 d->ref.ref();
119 }
120}
121
122/*!
123 Destroys this collator.
124*/
125QCollator::~QCollator()
126{
127 if (d && !d->ref.deref())
128 delete d;
129}
130
131/*!
132 Assigns \a other to this collator.
133*/
134QCollator &QCollator::operator=(const QCollator &other)
135{
136 if (this != &other) {
137 if (d && !d->ref.deref())
138 delete d;
139 d = other.d;
140 if (d) {
141 // Ensure clean, lest both copies try to init() at the same time:
142 d->ensureInitialized();
143 d->ref.ref();
144 }
145 }
146 return *this;
147}
148
149/*!
150 \fn QCollator::QCollator(QCollator &&other)
151
152 Move constructor. Moves from \a other into this collator.
153
154//! [partially-formed]
155 \note The moved-from object \a other is placed in a partially-formed state,
156 in which the only valid operations are destruction and assignment of a new
157 value.
158//! [partially-formed]
159*/
160
161/*!
162 \fn QCollator & QCollator::operator=(QCollator && other)
163
164 Move-assigns \a other to this QCollator instance.
165
166 \include qcollator.cpp partially-formed
167*/
168
169/*!
170 \fn void QCollator::swap(QCollator &other)
171 \memberswap{collator}
172*/
173
174/*!
175 \internal
176*/
177void QCollator::detach()
178{
179 if (d->ref.loadRelaxed() != 1) {
180 QCollatorPrivate *x = new QCollatorPrivate(d->locale);
181 if (!d->ref.deref())
182 delete d;
183 d = x;
184 }
185 // All callers need this, because about to modify the object:
186 d->dirty = true;
187}
188
189/*!
190 Sets the locale of the collator to \a locale.
191
192 \sa locale()
193*/
194void QCollator::setLocale(const QLocale &locale)
195{
196 if (locale == d->locale)
197 return;
198
199 detach();
200 d->locale = locale;
201}
202
203/*!
204 Returns the locale of the collator.
205
206 Unless supplied to the constructor or by calling setLocale(), the system's
207 default collation locale is used.
208
209 \sa setLocale(), QLocale::collation()
210*/
211QLocale QCollator::locale() const
212{
213 return d->locale;
214}
215
216/*!
217 Sets the case-sensitivity of the collator to \a cs.
218
219 \sa caseSensitivity()
220*/
221void QCollator::setCaseSensitivity(Qt::CaseSensitivity cs)
222{
223 if (d->caseSensitivity == cs)
224 return;
225
226 detach();
227 d->caseSensitivity = cs;
228}
229
230/*!
231 Returns case sensitivity of the collator.
232
233 This defaults to case-sensitive until set.
234
235 \note In the C locale, when case-sensitive, all lower-case letters sort
236 after all upper-case letters, where most locales sort each lower-case letter
237 either immediately before or immediately after its upper-case partner. Thus
238 "Zap" sorts before "ape" in the C locale but after in most others.
239
240 \sa setCaseSensitivity()
241*/
242Qt::CaseSensitivity QCollator::caseSensitivity() const
243{
244 return d->caseSensitivity;
245}
246
247/*!
248 Enables numeric sorting mode when \a on is \c true.
249
250 \sa numericMode()
251*/
252void QCollator::setNumericMode(bool on)
253{
254 if (d->numericMode == on)
255 return;
256
257 detach();
258 d->numericMode = on;
259}
260
261/*!
262 Returns \c true if numeric sorting is enabled, \c false otherwise.
263
264 When \c true, numerals are recognized as numbers and sorted in arithmetic
265 order; for example, 100 sortes after 99. When \c false, numbers are sorted
266 in lexical order, so that 100 sorts before 99 (because 1 is before 9). By
267 default, this option is disabled.
268
269 \sa setNumericMode()
270*/
271bool QCollator::numericMode() const
272{
273 return d->numericMode;
274}
275
276/*!
277 Ignores punctuation and symbols if \a on is \c true, attends to them if \c false.
278
279 \sa ignorePunctuation()
280*/
281void QCollator::setIgnorePunctuation(bool on)
282{
283 if (d->ignorePunctuation == on)
284 return;
285
286 detach();
287 d->ignorePunctuation = on;
288}
289
290/*!
291 Returns whether punctuation and symbols are ignored when collating.
292
293 When \c true, strings are compared as if all punctuation and symbols were
294 removed from each string.
295
296 \sa setIgnorePunctuation()
297*/
298bool QCollator::ignorePunctuation() const
299{
300 return d->ignorePunctuation;
301}
302
303/*!
304 \since 5.13
305 \fn bool QCollator::operator()(QStringView s1, QStringView s2) const
306
307 A QCollator can be used as the comparison function of a sorting algorithm.
308 It returns \c true if \a s1 sorts before \a s2, otherwise \c false.
309
310 \sa compare()
311*/
312
313/*!
314 \since 5.13
315 \fn int QCollator::compare(QStringView s1, QStringView s2) const
316
317 Compares \a s1 with \a s2.
318
319 Returns a negative integer if \a s1 is less than \a s2, a positive integer
320 if it is greater than \a s2, and zero if they are equal.
321*/
322
323/*!
324 \fn bool QCollator::operator()(const QString &s1, const QString &s2) const
325 \overload
326 \since 5.2
327*/
328
329/*!
330 \fn int QCollator::compare(const QString &s1, const QString &s2) const
331 \overload
332 \since 5.2
333*/
334
335/*!
336 \fn int QCollator::compare(const QChar *s1, qsizetype len1, const QChar *s2, qsizetype len2) const
337 \overload
338 \since 5.2
339
340 Compares \a s1 with \a s2. \a len1 and \a len2 specify the lengths of the
341 QChar arrays pointed to by \a s1 and \a s2.
342
343 Returns a negative integer if \a s1 is less than \a s2, a positive integer
344 if it is greater than \a s2, and zero if they are equal.
345
346
347 \note In Qt versions prior to 6.4, the length arguments were of type
348 \c{int}, not \c{qsizetype}.
349*/
350
351/*!
352 \since 6.3
353
354 Compares the strings \a s1 and \a s2, returning their sorting order. This
355 function performs the same operation as compare() on a default-constructed
356 QCollator object.
357
358 \sa compare(), defaultSortKey()
359*/
360int QCollator::defaultCompare(QStringView s1, QStringView s2)
361{
362 return defaultCollator->localData().collator().compare(s1, s2);
363}
364
365/*!
366 \since 6.3
367
368 Returns the sort key for the string \a key. This function performs the same
369 operation as sortKey() on a default-constructed QCollator object.
370
371 \sa sortKey(), defaultCompare()
372*/
373QCollatorSortKey QCollator::defaultSortKey(QStringView key)
374{
375 return defaultCollator->localData().collator().sortKey(key.toString());
376}
377
378/*!
379 \fn QCollatorSortKey QCollator::sortKey(const QString &string) const
380
381 Returns a sortKey for \a string.
382
383 Creating the sort key is usually somewhat slower, than using the compare()
384 methods directly. But if the string is compared repeatedly (e.g. when
385 sorting a whole list of strings), it's usually faster to create the sort
386 keys for each string and then sort using the keys.
387
388 \note Not supported with the C (a.k.a. POSIX) locale on Darwin.
389*/
390
391/*!
392 \class QCollatorSortKey
393 \inmodule QtCore
394 \brief The QCollatorSortKey class can be used to speed up string collation.
395
396 \since 5.2
397
398 The QCollatorSortKey class is always created by QCollator::sortKey() and is
399 used for fast strings collation, for example when collating many strings.
400
401 \reentrant
402 \ingroup i18n
403 \ingroup string-processing
404 \ingroup shared
405
406 \sa QCollator, QCollator::sortKey(), compare()
407*/
408
409/*!
410 \internal
411*/
412QCollatorSortKey::QCollatorSortKey(QCollatorSortKeyPrivate *d)
413 : d(d)
414{
415}
416
417/*!
418 Constructs a copy of the \a other collator key.
419*/
420QCollatorSortKey::QCollatorSortKey(const QCollatorSortKey &other)
421 : d(other.d)
422{
423}
424
425/*!
426 \since 6.8
427 \fn QCollatorSortKey::QCollatorSortKey(QCollatorSortKey &&other)
428 Move-constructs a new QCollatorSortKey from \a other.
429
430 \include qcollator.cpp partially-formed
431*/
432
433/*!
434 Destroys the collator key.
435*/
436QCollatorSortKey::~QCollatorSortKey()
437{
438}
439
440/*!
441 Assigns \a other to this collator key.
442*/
443QCollatorSortKey& QCollatorSortKey::operator=(const QCollatorSortKey &other)
444{
445 if (this != &other) {
446 d = other.d;
447 }
448 return *this;
449}
450
451/*!
452 \fn QCollatorSortKey &QCollatorSortKey::operator=(QCollatorSortKey && other)
453
454 Move-assigns \a other to this QCollatorSortKey instance.
455
456 \include qcollator.cpp partially-formed
457*/
458
459/*!
460 \fn bool QCollatorSortKey::operator<(const QCollatorSortKey &lhs, const QCollatorSortKey &rhs)
461
462 Both keys must have been created by the same QCollator's sortKey(). Returns
463 \c true if \a lhs should be sorted before \a rhs, according to the QCollator
464 that created them; otherwise returns \c false.
465
466 \sa QCollatorSortKey::compare()
467*/
468
469/*!
470 \fn void QCollatorSortKey::swap(QCollatorSortKey & other)
471 \memberswap{collator key}
472*/
473
474/*!
475 \fn int QCollatorSortKey::compare(const QCollatorSortKey &otherKey) const
476
477 Compares this key to \a otherKey, which must have been created by the same
478 QCollator's sortKey() as this key. The comparison is performed in accordance
479 with that QCollator's sort order.
480
481 Returns a negative value if this key sorts before \a otherKey, 0 if the two
482 keys are equal or a positive value if this key sorts after \a otherKey.
483
484 \sa operator<()
485*/
486
487QT_END_NAMESPACE
Combined button and popup list for selecting options.
GenerationalCollator(const QCollator &copy)
Definition qcollator.cpp:23