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
47 QT_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 system's default collation locale.
76
77 \sa setLocale(), QLocale::collation()
78 */
QCollator()79 QCollator::QCollator()
80 : d(new QCollatorPrivate(QLocale::system().collation()))
81 {
82 d->init();
83 }
84
85 /*!
86 Constructs a QCollator from \a locale.
87
88 \sa setLocale()
89 */
QCollator(const QLocale & locale)90 QCollator::QCollator(const QLocale &locale)
91 : d(new QCollatorPrivate(locale))
92 {
93 }
94
95 /*!
96 Creates a copy of \a other.
97 */
QCollator(const QCollator & other)98 QCollator::QCollator(const QCollator &other)
99 : d(other.d)
100 {
101 if (d) {
102 // Ensure clean, lest both copies try to init() at the same time:
103 if (d->dirty)
104 d->init();
105 d->ref.ref();
106 }
107 }
108
109 /*!
110 Destroys the collator.
111 */
~QCollator()112 QCollator::~QCollator()
113 {
114 if (d && !d->ref.deref())
115 delete d;
116 }
117
118 /*!
119 Assigns \a other to this collator.
120 */
operator =(const QCollator & other)121 QCollator &QCollator::operator=(const QCollator &other)
122 {
123 if (this != &other) {
124 if (d && !d->ref.deref())
125 delete d;
126 d = other.d;
127 if (d) {
128 // Ensure clean, lest both copies try to init() at the same time:
129 if (d->dirty)
130 d->init();
131 d->ref.ref();
132 }
133 }
134 return *this;
135 }
136
137 /*!
138 \fn QCollator::QCollator(QCollator &&other)
139
140 Move constructor. Moves from \a other into this collator.
141
142 Note that a moved-from QCollator can only be destroyed or assigned to.
143 The effect of calling other functions than the destructor or one of the
144 assignment operators is undefined.
145 */
146
147 /*!
148 \fn QCollator & QCollator::operator=(QCollator && other)
149
150 Move-assigns from \a other to this collator.
151
152 Note that a moved-from QCollator can only be destroyed or assigned to.
153 The effect of calling other functions than the destructor or one of the
154 assignment operators is undefined.
155 */
156
157 /*!
158 \fn void QCollator::swap(QCollator &other)
159
160 Swaps this collator with \a other. This function is very fast and
161 never fails.
162 */
163
164 /*!
165 \internal
166 */
detach()167 void QCollator::detach()
168 {
169 if (d->ref.loadRelaxed() != 1) {
170 QCollatorPrivate *x = new QCollatorPrivate(d->locale);
171 if (!d->ref.deref())
172 delete d;
173 d = x;
174 }
175 // All callers need this, because about to modify the object:
176 d->dirty = true;
177 }
178
179 /*!
180 Sets the locale of the collator to \a locale.
181 */
setLocale(const QLocale & locale)182 void QCollator::setLocale(const QLocale &locale)
183 {
184 if (locale == d->locale)
185 return;
186
187 detach();
188 d->locale = locale;
189 }
190
191 /*!
192 Returns the locale of the collator.
193 */
locale() const194 QLocale QCollator::locale() const
195 {
196 return d->locale;
197 }
198
199 /*!
200 \fn void QCollator::setCaseSensitivity(Qt::CaseSensitivity sensitivity)
201
202 Sets the case \a sensitivity of the collator.
203
204 \sa caseSensitivity()
205 */
setCaseSensitivity(Qt::CaseSensitivity cs)206 void QCollator::setCaseSensitivity(Qt::CaseSensitivity cs)
207 {
208 if (d->caseSensitivity == cs)
209 return;
210
211 detach();
212 d->caseSensitivity = cs;
213 }
214
215 /*!
216 \fn Qt::CaseSensitivity QCollator::caseSensitivity() const
217
218 Returns case sensitivity of the collator.
219
220 \sa setCaseSensitivity()
221 */
caseSensitivity() const222 Qt::CaseSensitivity QCollator::caseSensitivity() const
223 {
224 return d->caseSensitivity;
225 }
226
227 /*!
228 \fn void QCollator::setNumericMode(bool on)
229
230 Enables numeric sorting mode when \a on is set to true.
231
232 This will enable proper sorting of numeric digits, so that e.g. 100 sorts
233 after 99.
234
235 By default this mode is off.
236
237 \sa numericMode()
238 */
setNumericMode(bool on)239 void QCollator::setNumericMode(bool on)
240 {
241 if (d->numericMode == on)
242 return;
243
244 detach();
245 d->numericMode = on;
246 }
247
248 /*!
249 \fn bool QCollator::numericMode() const
250
251 Returns \c true if numeric sorting is enabled, false otherwise.
252
253 \sa setNumericMode()
254 */
numericMode() const255 bool QCollator::numericMode() const
256 {
257 return d->numericMode;
258 }
259
260 /*!
261 \fn void QCollator::setIgnorePunctuation(bool on)
262
263 If \a on is set to true, punctuation characters and symbols are ignored when
264 determining sort order.
265
266 The default is locale dependent.
267
268 \note This method is not currently supported if Qt is configured to not use
269 ICU on Linux.
270
271 \sa ignorePunctuation()
272 */
setIgnorePunctuation(bool on)273 void QCollator::setIgnorePunctuation(bool on)
274 {
275 if (d->ignorePunctuation == on)
276 return;
277
278 detach();
279 d->ignorePunctuation = on;
280 }
281
282 /*!
283 \fn bool QCollator::ignorePunctuation() const
284
285 Returns \c true if punctuation characters and symbols are ignored when
286 determining sort order.
287
288 \sa setIgnorePunctuation()
289 */
ignorePunctuation() const290 bool QCollator::ignorePunctuation() const
291 {
292 return d->ignorePunctuation;
293 }
294
295 /*!
296 \since 5.13
297 \fn bool QCollator::operator()(QStringView s1, QStringView s2) const
298 \internal
299 */
300
301 /*!
302 \since 5.13
303 \fn int QCollator::compare(QStringView s1, QStringView s2) const
304
305 Compares \a s1 with \a s2.
306
307 Returns an integer less than, equal to, or greater than zero depending on
308 whether \a s1 sorts before, with or after \a s2.
309 */
310 #if QT_STRINGVIEW_LEVEL < 2
311 /*!
312 \fn bool QCollator::operator()(const QString &s1, const QString &s2) const
313 \internal
314 */
315
316 /*!
317 \overload
318
319 Compares \a s1 with \a s2.
320
321 Returns an integer less than, equal to, or greater than zero depending on
322 whether \a s1 sorts before, with or after \a s2.
323 */
compare(const QString & s1,const QString & s2) const324 int QCollator::compare(const QString &s1, const QString &s2) const
325 {
326 return compare(QStringView(s1), QStringView(s2));
327 }
328
329 /*!
330 \overload
331
332 Compares \a s1 with \a s2.
333
334 Returns an integer less than, equal to, or greater than zero depending on
335 whether \a s1 sorts before, with or after \a s2.
336 */
compare(const QStringRef & s1,const QStringRef & s2) const337 int QCollator::compare(const QStringRef &s1, const QStringRef &s2) const
338 {
339 return compare(QStringView(s1), QStringView(s2));
340 }
341
342 /*!
343 \overload
344
345 Compares \a s1 with \a s2. \a len1 and \a len2 specify the lengths of the
346 QChar arrays pointed to by \a s1 and \a s2.
347
348 Returns an integer less than, equal to, or greater than zero depending on
349 whether \a s1 sorts before, with or after \a s2.
350 */
compare(const QChar * s1,int len1,const QChar * s2,int len2) const351 int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) const
352 {
353 return compare(QStringView(s1, len1), QStringView(s2, len2));
354 }
355 #endif // QT_STRINGVIEW_LEVEL < 2
356
357 /*!
358 \fn QCollatorSortKey QCollator::sortKey(const QString &string) const
359
360 Returns a sortKey for \a string.
361
362 Creating the sort key is usually somewhat slower, than using the compare()
363 methods directly. But if the string is compared repeatedly (e.g. when
364 sorting a whole list of strings), it's usually faster to create the sort
365 keys for each string and then sort using the keys.
366
367 \note Not supported with the C (a.k.a. POSIX) locale on Darwin.
368 */
369
370 /*!
371 \class QCollatorSortKey
372 \inmodule QtCore
373 \brief The QCollatorSortKey class can be used to speed up string collation.
374
375 \since 5.2
376
377 The QCollatorSortKey class is always created by QCollator::sortKey() and is
378 used for fast strings collation, for example when collating many strings.
379
380 \reentrant
381 \ingroup i18n
382 \ingroup string-processing
383 \ingroup shared
384
385 \sa QCollator, QCollator::sortKey()
386 */
387
388 /*!
389 \internal
390 */
QCollatorSortKey(QCollatorSortKeyPrivate * d)391 QCollatorSortKey::QCollatorSortKey(QCollatorSortKeyPrivate *d)
392 : d(d)
393 {
394 }
395
396 /*!
397 Constructs a copy of the \a other collator key.
398 */
QCollatorSortKey(const QCollatorSortKey & other)399 QCollatorSortKey::QCollatorSortKey(const QCollatorSortKey &other)
400 : d(other.d)
401 {
402 }
403
404 /*!
405 Destroys the collator key.
406 */
~QCollatorSortKey()407 QCollatorSortKey::~QCollatorSortKey()
408 {
409 }
410
411 /*!
412 Assigns \a other to this collator key.
413 */
operator =(const QCollatorSortKey & other)414 QCollatorSortKey& QCollatorSortKey::operator=(const QCollatorSortKey &other)
415 {
416 if (this != &other) {
417 d = other.d;
418 }
419 return *this;
420 }
421
422 /*!
423 \fn QCollatorSortKey &QCollatorSortKey::operator=(QCollatorSortKey && other)
424
425 Move-assigns \a other to this collator key.
426 */
427
428 /*!
429 \fn bool operator<(const QCollatorSortKey &lhs, const QCollatorSortKey &rhs)
430 \relates QCollatorSortKey
431
432 According to the QCollator that created the keys, returns \c true if \a lhs
433 should be sorted before \a rhs; otherwise returns \c false.
434
435 \sa QCollatorSortKey::compare()
436 */
437
438 /*!
439 \fn void QCollatorSortKey::swap(QCollatorSortKey & other)
440
441 Swaps this collator key with \a other.
442 */
443
444 /*!
445 \fn int QCollatorSortKey::compare(const QCollatorSortKey &otherKey) const
446
447 Compares this key to \a otherKey.
448
449 Returns a negative value if the key is less than \a otherKey, 0 if the key
450 is equal to \a otherKey or a positive value if the key is greater than \a
451 otherKey.
452
453 \sa operator<()
454 */
455
456 QT_END_NAMESPACE
457