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 | */ |
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 | */ |
90 | QCollator::QCollator(const QLocale &locale) |
91 | : d(new QCollatorPrivate(locale)) |
92 | { |
93 | } |
94 | |
95 | /*! |
96 | Creates a copy of \a other. |
97 | */ |
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 | */ |
112 | QCollator::~QCollator() |
113 | { |
114 | if (d && !d->ref.deref()) |
115 | delete d; |
116 | } |
117 | |
118 | /*! |
119 | Assigns \a other to this collator. |
120 | */ |
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 | */ |
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 | */ |
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 | */ |
194 | 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 | */ |
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 | */ |
222 | 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 | */ |
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 | */ |
255 | 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 | */ |
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 | */ |
290 | 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 | */ |
324 | 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. \a len1 and \a len2 specify the lengths of the |
333 | QChar arrays pointed to by \a s1 and \a s2. |
334 | |
335 | Returns an integer less than, equal to, or greater than zero depending on |
336 | whether \a s1 sorts before, with or after \a s2. |
337 | */ |
338 | int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) const |
339 | { |
340 | return compare(QStringView(s1, len1), QStringView(s2, len2)); |
341 | } |
342 | #endif // QT_STRINGVIEW_LEVEL < 2 |
343 | |
344 | /*! |
345 | \fn QCollatorSortKey QCollator::sortKey(const QString &string) const |
346 | |
347 | Returns a sortKey for \a string. |
348 | |
349 | Creating the sort key is usually somewhat slower, than using the compare() |
350 | methods directly. But if the string is compared repeatedly (e.g. when |
351 | sorting a whole list of strings), it's usually faster to create the sort |
352 | keys for each string and then sort using the keys. |
353 | |
354 | \note Not supported with the C (a.k.a. POSIX) locale on Darwin. |
355 | */ |
356 | |
357 | /*! |
358 | \class QCollatorSortKey |
359 | \inmodule QtCore |
360 | \brief The QCollatorSortKey class can be used to speed up string collation. |
361 | |
362 | \since 5.2 |
363 | |
364 | The QCollatorSortKey class is always created by QCollator::sortKey() and is |
365 | used for fast strings collation, for example when collating many strings. |
366 | |
367 | \reentrant |
368 | \ingroup i18n |
369 | \ingroup string-processing |
370 | \ingroup shared |
371 | |
372 | \sa QCollator, QCollator::sortKey() |
373 | */ |
374 | |
375 | /*! |
376 | \internal |
377 | */ |
378 | QCollatorSortKey::QCollatorSortKey(QCollatorSortKeyPrivate *d) |
379 | : d(d) |
380 | { |
381 | } |
382 | |
383 | /*! |
384 | Constructs a copy of the \a other collator key. |
385 | */ |
386 | QCollatorSortKey::QCollatorSortKey(const QCollatorSortKey &other) |
387 | : d(other.d) |
388 | { |
389 | } |
390 | |
391 | /*! |
392 | Destroys the collator key. |
393 | */ |
394 | QCollatorSortKey::~QCollatorSortKey() |
395 | { |
396 | } |
397 | |
398 | /*! |
399 | Assigns \a other to this collator key. |
400 | */ |
401 | QCollatorSortKey& QCollatorSortKey::operator=(const QCollatorSortKey &other) |
402 | { |
403 | if (this != &other) { |
404 | d = other.d; |
405 | } |
406 | return *this; |
407 | } |
408 | |
409 | /*! |
410 | \fn QCollatorSortKey &QCollatorSortKey::operator=(QCollatorSortKey && other) |
411 | |
412 | Move-assigns \a other to this collator key. |
413 | */ |
414 | |
415 | /*! |
416 | \fn bool operator<(const QCollatorSortKey &lhs, const QCollatorSortKey &rhs) |
417 | \relates QCollatorSortKey |
418 | |
419 | According to the QCollator that created the keys, returns \c true if \a lhs |
420 | should be sorted before \a rhs; otherwise returns \c false. |
421 | |
422 | \sa QCollatorSortKey::compare() |
423 | */ |
424 | |
425 | /*! |
426 | \fn void QCollatorSortKey::swap(QCollatorSortKey & other) |
427 | |
428 | Swaps this collator key with \a other. |
429 | */ |
430 | |
431 | /*! |
432 | \fn int QCollatorSortKey::compare(const QCollatorSortKey &otherKey) const |
433 | |
434 | Compares this key to \a otherKey. |
435 | |
436 | Returns a negative value if the key is less than \a otherKey, 0 if the key |
437 | is equal to \a otherKey or a positive value if the key is greater than \a |
438 | otherKey. |
439 | |
440 | \sa operator<() |
441 | */ |
442 | |
443 | QT_END_NAMESPACE |
444 | |