1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Copyright (C) 2013 Aleix Pol Gonzalez <aleixpol@kde.org>
5** Contact: https://www.qt.io/licensing/
6**
7** This file is part of the QtCore module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial License Usage
11** Licensees holding valid commercial Qt licenses may use this file in
12** accordance with the commercial license agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and The Qt Company. For licensing terms
15** and conditions see https://www.qt.io/terms-conditions. For further
16** information use the contact form at https://www.qt.io/contact-us.
17**
18** GNU Lesser General Public License Usage
19** Alternatively, this file may be used under the terms of the GNU Lesser
20** General Public License version 3 as published by the Free Software
21** Foundation and appearing in the file LICENSE.LGPL3 included in the
22** packaging of this file. Please review the following information to
23** ensure the GNU Lesser General Public License version 3 requirements
24** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25**
26** GNU General Public License Usage
27** Alternatively, this file may be used under the terms of the GNU
28** General Public License version 2.0 or (at your option) the GNU General
29** Public license version 3 or any later version approved by the KDE Free
30** Qt Foundation. The licenses are as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32** included in the packaging of this file. Please review the following
33** information to ensure the GNU General Public License requirements will
34** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35** https://www.gnu.org/licenses/gpl-3.0.html.
36**
37** $QT_END_LICENSE$
38**
39****************************************************************************/
40
41#include "qcollator_p.h"
42#include "qstringlist.h"
43#include "qstring.h"
44
45#include "qdebug.h"
46
47QT_BEGIN_NAMESPACE
48
49/*!
50 \class QCollator
51 \inmodule QtCore
52 \brief The QCollator class compares strings according to a localized collation algorithm.
53
54 \since 5.2
55
56 \reentrant
57 \ingroup i18n
58 \ingroup string-processing
59 \ingroup shared
60
61 QCollator is initialized with a QLocale and an optional collation strategy.
62 It tries to initialize the collator with the specified values. The collator
63 can then be used to compare and sort strings in a locale dependent fashion.
64
65 A QCollator object can be used together with template based sorting
66 algorithms such as std::sort to sort a list of QStrings.
67
68 In addition to the locale and collation strategy, several optional flags can
69 be set that influence the result of the collation.
70*/
71
72/*!
73 \since 5.13
74
75 Constructs a QCollator using the default locale's collation locale.
76
77 The system locale, when used as default locale, may have a collation locale
78 other than itself (e.g. on Unix, if LC_COLLATE is set differently to LANG in
79 the environment). All other locales are their own collation locales.
80
81 \sa setLocale(), QLocale::collation(), QLocale::setDefault()
82*/
83QCollator::QCollator()
84 : d(new QCollatorPrivate(QLocale().collation()))
85{
86 d->init();
87}
88
89/*!
90 Constructs a QCollator from \a locale.
91
92 \sa setLocale()
93 */
94QCollator::QCollator(const QLocale &locale)
95 : d(new QCollatorPrivate(locale))
96{
97}
98
99/*!
100 Creates a copy of \a other.
101 */
102QCollator::QCollator(const QCollator &other)
103 : d(other.d)
104{
105 if (d) {
106 // Ensure clean, lest both copies try to init() at the same time:
107 if (d->dirty)
108 d->init();
109 d->ref.ref();
110 }
111}
112
113/*!
114 Destroys the collator.
115 */
116QCollator::~QCollator()
117{
118 if (d && !d->ref.deref())
119 delete d;
120}
121
122/*!
123 Assigns \a other to this collator.
124 */
125QCollator &QCollator::operator=(const QCollator &other)
126{
127 if (this != &other) {
128 if (d && !d->ref.deref())
129 delete d;
130 d = other.d;
131 if (d) {
132 // Ensure clean, lest both copies try to init() at the same time:
133 if (d->dirty)
134 d->init();
135 d->ref.ref();
136 }
137 }
138 return *this;
139}
140
141/*!
142 \fn QCollator::QCollator(QCollator &&other)
143
144 Move constructor. Moves from \a other into this collator.
145
146 Note that a moved-from QCollator can only be destroyed or assigned to.
147 The effect of calling other functions than the destructor or one of the
148 assignment operators is undefined.
149*/
150
151/*!
152 \fn QCollator & QCollator::operator=(QCollator && other)
153
154 Move-assigns from \a other to this collator.
155
156 Note that a moved-from QCollator can only be destroyed or assigned to.
157 The effect of calling other functions than the destructor or one of the
158 assignment operators is undefined.
159*/
160
161/*!
162 \fn void QCollator::swap(QCollator &other)
163
164 Swaps this collator with \a other. This function is very fast and
165 never fails.
166*/
167
168/*!
169 \internal
170 */
171void QCollator::detach()
172{
173 if (d->ref.loadRelaxed() != 1) {
174 QCollatorPrivate *x = new QCollatorPrivate(d->locale);
175 if (!d->ref.deref())
176 delete d;
177 d = x;
178 }
179 // All callers need this, because about to modify the object:
180 d->dirty = true;
181}
182
183/*!
184 Sets the locale of the collator to \a locale.
185 */
186void QCollator::setLocale(const QLocale &locale)
187{
188 if (locale == d->locale)
189 return;
190
191 detach();
192 d->locale = locale;
193}
194
195/*!
196 Returns the locale of the collator.
197 */
198QLocale QCollator::locale() const
199{
200 return d->locale;
201}
202
203/*!
204 \fn void QCollator::setCaseSensitivity(Qt::CaseSensitivity sensitivity)
205
206 Sets the case \a sensitivity of the collator.
207
208 \sa caseSensitivity()
209 */
210void QCollator::setCaseSensitivity(Qt::CaseSensitivity cs)
211{
212 if (d->caseSensitivity == cs)
213 return;
214
215 detach();
216 d->caseSensitivity = cs;
217}
218
219/*!
220 \fn Qt::CaseSensitivity QCollator::caseSensitivity() const
221
222 Returns case sensitivity of the collator.
223
224 \sa setCaseSensitivity()
225 */
226Qt::CaseSensitivity QCollator::caseSensitivity() const
227{
228 return d->caseSensitivity;
229}
230
231/*!
232 \fn void QCollator::setNumericMode(bool on)
233
234 Enables numeric sorting mode when \a on is set to true.
235
236 This will enable proper sorting of numeric digits, so that e.g. 100 sorts
237 after 99.
238
239 By default this mode is off.
240
241 \sa numericMode()
242 */
243void QCollator::setNumericMode(bool on)
244{
245 if (d->numericMode == on)
246 return;
247
248 detach();
249 d->numericMode = on;
250}
251
252/*!
253 \fn bool QCollator::numericMode() const
254
255 Returns \c true if numeric sorting is enabled, false otherwise.
256
257 \sa setNumericMode()
258 */
259bool QCollator::numericMode() const
260{
261 return d->numericMode;
262}
263
264/*!
265 \fn void QCollator::setIgnorePunctuation(bool on)
266
267 If \a on is set to true, punctuation characters and symbols are ignored when
268 determining sort order.
269
270 The default is locale dependent.
271
272 \note This method is not currently supported if Qt is configured to not use
273 ICU on Linux.
274
275 \sa ignorePunctuation()
276 */
277void QCollator::setIgnorePunctuation(bool on)
278{
279 if (d->ignorePunctuation == on)
280 return;
281
282 detach();
283 d->ignorePunctuation = on;
284}
285
286/*!
287 \fn bool QCollator::ignorePunctuation() const
288
289 Returns \c true if punctuation characters and symbols are ignored when
290 determining sort order.
291
292 \sa setIgnorePunctuation()
293 */
294bool QCollator::ignorePunctuation() const
295{
296 return d->ignorePunctuation;
297}
298
299/*!
300 \since 5.13
301 \fn bool QCollator::operator()(QStringView s1, QStringView s2) const
302 \internal
303*/
304
305/*!
306 \since 5.13
307 \fn int QCollator::compare(QStringView s1, QStringView s2) const
308
309 Compares \a s1 with \a s2.
310
311 Returns an integer less than, equal to, or greater than zero depending on
312 whether \a s1 sorts before, with or after \a s2.
313*/
314#if QT_STRINGVIEW_LEVEL < 2
315/*!
316 \fn bool QCollator::operator()(const QString &s1, const QString &s2) const
317 \internal
318*/
319
320/*!
321 \overload
322
323 Compares \a s1 with \a s2.
324
325 Returns an integer less than, equal to, or greater than zero depending on
326 whether \a s1 sorts before, with or after \a s2.
327*/
328int QCollator::compare(const QString &s1, const QString &s2) const
329{
330 return compare(s1: QStringView(s1), s2: QStringView(s2));
331}
332
333/*!
334 \overload
335
336 Compares \a s1 with \a s2.
337
338 Returns an integer less than, equal to, or greater than zero depending on
339 whether \a s1 sorts before, with or after \a s2.
340 */
341int QCollator::compare(const QStringRef &s1, const QStringRef &s2) const
342{
343 return compare(s1: QStringView(s1), s2: QStringView(s2));
344}
345
346/*!
347 \overload
348
349 Compares \a s1 with \a s2. \a len1 and \a len2 specify the lengths of the
350 QChar arrays pointed to by \a s1 and \a s2.
351
352 Returns an integer less than, equal to, or greater than zero depending on
353 whether \a s1 sorts before, with or after \a s2.
354*/
355int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) const
356{
357 return compare(s1: QStringView(s1, len1), s2: QStringView(s2, len2));
358}
359#endif // QT_STRINGVIEW_LEVEL < 2
360
361/*!
362 \fn QCollatorSortKey QCollator::sortKey(const QString &string) const
363
364 Returns a sortKey for \a string.
365
366 Creating the sort key is usually somewhat slower, than using the compare()
367 methods directly. But if the string is compared repeatedly (e.g. when
368 sorting a whole list of strings), it's usually faster to create the sort
369 keys for each string and then sort using the keys.
370
371 \note Not supported with the C (a.k.a. POSIX) locale on Darwin.
372 */
373
374/*!
375 \class QCollatorSortKey
376 \inmodule QtCore
377 \brief The QCollatorSortKey class can be used to speed up string collation.
378
379 \since 5.2
380
381 The QCollatorSortKey class is always created by QCollator::sortKey() and is
382 used for fast strings collation, for example when collating many strings.
383
384 \reentrant
385 \ingroup i18n
386 \ingroup string-processing
387 \ingroup shared
388
389 \sa QCollator, QCollator::sortKey()
390*/
391
392/*!
393 \internal
394 */
395QCollatorSortKey::QCollatorSortKey(QCollatorSortKeyPrivate *d)
396 : d(d)
397{
398}
399
400/*!
401 Constructs a copy of the \a other collator key.
402*/
403QCollatorSortKey::QCollatorSortKey(const QCollatorSortKey &other)
404 : d(other.d)
405{
406}
407
408/*!
409 Destroys the collator key.
410 */
411QCollatorSortKey::~QCollatorSortKey()
412{
413}
414
415/*!
416 Assigns \a other to this collator key.
417 */
418QCollatorSortKey& QCollatorSortKey::operator=(const QCollatorSortKey &other)
419{
420 if (this != &other) {
421 d = other.d;
422 }
423 return *this;
424}
425
426/*!
427 \fn QCollatorSortKey &QCollatorSortKey::operator=(QCollatorSortKey && other)
428
429 Move-assigns \a other to this collator key.
430*/
431
432/*!
433 \fn bool operator<(const QCollatorSortKey &lhs, const QCollatorSortKey &rhs)
434 \relates QCollatorSortKey
435
436 According to the QCollator that created the keys, returns \c true if \a lhs
437 should be sorted before \a rhs; otherwise returns \c false.
438
439 \sa QCollatorSortKey::compare()
440 */
441
442/*!
443 \fn void QCollatorSortKey::swap(QCollatorSortKey & other)
444
445 Swaps this collator key with \a other.
446*/
447
448/*!
449 \fn int QCollatorSortKey::compare(const QCollatorSortKey &otherKey) const
450
451 Compares this key to \a otherKey.
452
453 Returns a negative value if the key is less than \a otherKey, 0 if the key
454 is equal to \a otherKey or a positive value if the key is greater than \a
455 otherKey.
456
457 \sa operator<()
458 */
459
460QT_END_NAMESPACE
461

source code of qtbase/src/corelib/text/qcollator.cpp