31using ucol_setAttribute_t =
void (*)(UCollator *, UColAttribute, UColAttributeValue, UErrorCode*);
34using ucol_getSortKey_t = int32_t (*)(
const UCollator*,
const UChar*, int32_t, uint8_t*, int32_t);
51void QCollatorPrivate::init()
57#if !QT_CONFIG(icu) && defined(Q_OS_ANDROID)
58 static bool icuLoaded = []() {
60 QLibrary icuLib(QStringLiteral(
"libicu"));
62 qWarning().nospace() <<
"ICU loading failed: " << icuLib.errorString()
63 <<
". Fallback collator will be used instead, not all features will be available.";
67 s_ucol.open =
reinterpret_cast<ucol_open_t>(icuLib.resolve(
"ucol_open"));
68 s_ucol.setAttribute =
reinterpret_cast<ucol_setAttribute_t>(icuLib.resolve(
"ucol_setAttribute"));
69 s_ucol.close =
reinterpret_cast<ucol_close_t>(icuLib.resolve(
"ucol_close"));
70 s_ucol.strcoll =
reinterpret_cast<ucol_strcoll_t>(icuLib.resolve(
"ucol_strcoll"));
71 s_ucol.getSortKey =
reinterpret_cast<ucol_getSortKey_t>(icuLib.resolve(
"ucol_getSortKey"));
72 return s_ucol.open && s_ucol.setAttribute && s_ucol.close && s_ucol.strcoll && s_ucol.getSortKey;
79 if (options.testFlag(Opt::DiacriticInsensitive) && options.testFlag(Opt::CaseInsensitive))
80 strength = UCOL_PRIMARY;
81 else if (options.testFlag(Opt::CaseInsensitive))
82 strength = UCOL_SECONDARY;
83 fallbackCollator = QtJniTypes::QtCollator::callStaticMethod<QtJniTypes::Collator>(
"getCollator", locale.bcp47Name(), strength);
89 UErrorCode status = U_ZERO_ERROR;
90 QByteArray name = QLocalePrivate::get(locale)->bcp47Name(
'_');
91 collator = ucol_open(name.constData(), &status);
92 if (U_FAILURE(status)) {
93 qWarning(
"Could not create collator: %d", status);
100 ucol_setAttribute(collator, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
109 if (options.testFlag(Opt::DiacriticInsensitive)) {
111 status = U_ZERO_ERROR;
112 ucol_setAttribute(collator, UCOL_STRENGTH, UCOL_PRIMARY, &status);
113 if (U_FAILURE(status))
114 qWarning(
"ucol_setAttribute: Diacritic and case insensitivity failed: %d", status);
116 if (!options.testFlag(Opt::CaseInsensitive)) {
118 status = U_ZERO_ERROR;
119 ucol_setAttribute(collator, UCOL_CASE_LEVEL, UCOL_ON, &status);
120 if (U_FAILURE(status)) {
121 qWarning(
"ucol_setAttribute: Diacritic insensitivity with case distinction failed:"
126 const UColAttributeValue strength
127 = options.testFlag(Opt::CaseInsensitive) ? UCOL_SECONDARY : UCOL_DEFAULT_STRENGTH;
129 status = U_ZERO_ERROR;
130 ucol_setAttribute(collator, UCOL_STRENGTH, strength, &status);
131 if (U_FAILURE(status))
132 qWarning(
"ucol_setAttribute: Case sensitivity failed: %d", status);
135 status = U_ZERO_ERROR;
136 ucol_setAttribute(collator, UCOL_NUMERIC_COLLATION,
137 options.testFlag(Opt::NumericSort) ? UCOL_ON : UCOL_OFF, &status);
138 if (U_FAILURE(status))
139 qWarning(
"ucol_setAttribute: numeric collation failed: %d", status);
141 status = U_ZERO_ERROR;
142 ucol_setAttribute(collator, UCOL_ALTERNATE_HANDLING,
143 options.testFlag(Opt::IgnorePunctuation) ? UCOL_SHIFTED
144 : UCOL_NON_IGNORABLE, &status);
145 if (U_FAILURE(status))
146 qWarning(
"ucol_setAttribute: Alternate handling failed: %d", status);
158int QCollator::compare(QStringView s1, QStringView s2)
const
161 return s2.size() ? -1 : 0;
166 d =
new QCollatorPrivate(QLocale().collation());
168 d->ensureInitialized();
172 return ucol_strcoll(d->collator,
173 reinterpret_cast<
const UChar *>(s1.data()), s1.size(),
174 reinterpret_cast<
const UChar *>(s2.data()), s2.size());
176#if !QT_CONFIG(icu) && defined(Q_OS_ANDROID)
177 else if (d->fallbackCollator.isValid()) {
178 return d->fallbackCollator.callMethod<
int>(
"compare", s1, s2);
182 return QtPrivate::compareStrings(s1, s2, caseSensitivity());
185QCollatorSortKey QCollator::sortKey(
const QString &string)
const
188 d =
new QCollatorPrivate(QLocale().collation());
190 d->ensureInitialized();
193 return QCollatorPrivate::sortKeyFromData(string.toUtf8());
196 QByteArray result(16 + string.size() + (string.size() >> 2), Qt::Uninitialized);
198 int size = ucol_getSortKey(d->collator, (
const UChar *)string.constData(),
199 string.size(), (uint8_t *)result.data(), result.size());
200 if (size > result.size()) {
202 size = ucol_getSortKey(d->collator, (
const UChar *)string.constData(),
203 string.size(), (uint8_t *)result.data(), result.size());
205 result.truncate(size);
206 return QCollatorPrivate::sortKeyFromData(std::move(result));
208#if !QT_CONFIG(icu) && defined(Q_OS_ANDROID)
209 else if (d->fallbackCollator.isValid()) {
210 return QCollatorPrivate::sortKeyFromData(QtJniTypes::QtCollator::callStaticMethod<QByteArray>(
"getCollationKey", d->fallbackCollator, string));
214 return QCollatorPrivate::sortKeyFromData(QByteArray());