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_win.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 Aleix Pol Gonzalez <aleixpol@kde.org>
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:critical reason:data-parser
4
5#include "qcollator_p.h"
6#include "qlocale_p.h"
7#include "qstringlist.h"
8#include "qstring.h"
9
10#include <QDebug>
11
12#include <qt_windows.h>
13#include <qsysinfo.h>
14
16
17//NOTE: SORT_DIGITSASNUMBERS is available since win7
18#ifndef SORT_DIGITSASNUMBERS
19#define SORT_DIGITSASNUMBERS 8
20#endif
21
23{
24 collator = 0;
25 if (isC())
26 return;
27
28 if (caseSensitivity == Qt::CaseInsensitive)
29 collator |= NORM_IGNORECASE;
30
31 // WINE does not support SORT_DIGITSASNUMBERS :-(
32 // (and its std::sort() crashes on bad comparisons, QTBUG-74209)
33 if (numericMode)
35
36 if (ignorePunctuation)
37 collator |= NORM_IGNORESYMBOLS;
38
39 dirty = false;
40}
41
43{
44}
45
46int QCollator::compare(QStringView s1, QStringView s2) const
47{
48 if (!s1.size())
49 return s2.size() ? -1 : 0;
50 if (!s2.size())
51 return +1;
52
53 if (!d)
54 d = new QCollatorPrivate(QCollatorPrivate(QLocale().collation()));
55
56 if (d->isC())
57 return s1.compare(s2, d->caseSensitivity);
58
59 d->ensureInitialized();
60
61 //* from Windows documentation *
62 // Returns one of the following values if successful. To maintain the C
63 // runtime convention of comparing strings, the value 2 can be subtracted
64 // from a nonzero return value. Then, the meaning of <0, ==0, and >0 is
65 // consistent with the C runtime.
66 // [...] The function returns 0 if it does not succeed.
67 // https://docs.microsoft.com/en-us/windows/desktop/api/stringapiset/nf-stringapiset-comparestringex#return-value
68
69 const QString locale = d->locale.bcp47Name();
70 const int ret = CompareStringEx(reinterpret_cast<const wchar_t *>(locale.constData()),
71 d->collator,
72 reinterpret_cast<const wchar_t *>(s1.data()), s1.size(),
73 reinterpret_cast<const wchar_t *>(s2.data()), s2.size(),
74 nullptr, nullptr, 0);
75 if (Q_LIKELY(ret))
76 return ret - 2;
77
78 switch (DWORD error = GetLastError()) {
79 case ERROR_INVALID_FLAGS:
80 qWarning("Unsupported flags (%d) used in QCollator", int(d->collator));
81 break;
82 case ERROR_INVALID_PARAMETER:
83 qWarning("Invalid parameter for QCollator::compare()");
84 break;
85 default:
86 qErrnoWarning(error, "Failed comparison in QCollator::compare()");
87 break;
88 }
89 // We have no idea what to return, so pretend we think they're equal.
90 // At least that way we'll be consistent if we get the same values swapped ...
91 return 0;
92}
93
94QCollatorSortKey QCollator::sortKey(const QString &string) const
95{
96 if (string.isEmpty()) {
97 // empty strings sort before everything and LCMapString doesn't
98 // like them
99 return QCollatorSortKey(nullptr);
100 }
101
102 if (!d)
103 d = new QCollatorPrivate(QCollatorPrivate(QLocale().collation()));
104 d->ensureInitialized();
105
106 if (d->isC())
107 return QCollatorSortKey(new QCollatorSortKeyPrivate(string.toUtf8()));
108
109 const QString localeName = d->locale.bcp47Name();
110 auto callLcMapString = [&](LPWSTR lpDestStr, int cchDest) {
111 // note: truncating sizes (QTBUG-105038)
112 return LCMapStringEx(reinterpret_cast<const wchar_t *>(localeName.constData()),
113 LCMAP_SORTKEY | d->collator,
114 reinterpret_cast<const wchar_t*>(string.constData()), string.size(),
115 lpDestStr, cchDest, nullptr, nullptr, 0);
116 };
117
118 int size = callLcMapString(nullptr, 0);
119 CollatorKeyType ret(size, Qt::Uninitialized);
120 size = callLcMapString(reinterpret_cast<wchar_t*>(ret.data()), ret.size());
121 if (size != ret.size())
122 ret.truncate(size);
123 if (size == 0)
124 qErrnoWarning("Error when generating the ::sortKey by LCMapStringEx");
125
126 return QCollatorSortKey(new QCollatorSortKeyPrivate(std::move(ret)));
127}
128
129int QCollatorSortKey::compare(const QCollatorSortKey &otherKey) const
130{
131 if (!d)
132 return otherKey.d ? -1 : 0;
133 if (!otherKey.d)
134 return +1;
135 return d->m_key.compare(otherKey.d->m_key);
136}
137
138QT_END_NAMESPACE
bool isC() const
Definition qcollator_p.h:68
CollatorType collator
Definition qcollator_p.h:64
Combined button and popup list for selecting options.
#define SORT_DIGITSASNUMBERS