QChar: make fullConvertCase()'s result type more usable
Move it into the function, give it an explicit size and make it iterable and indicate to QStringView that it's a compatible container. Change-Id: I483d9225ac73ad93f2037489f2d32473c377e8b7 Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
parent
e875f45805
commit
fae7a47bb3
@ -1590,11 +1590,21 @@ QChar::UnicodeVersion QChar::currentUnicodeVersion() noexcept
|
|||||||
return UNICODE_DATA_VERSION;
|
return UNICODE_DATA_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
using FullConvertCaseResult = std::array<char16_t, MaxSpecialCaseLength + 1>;
|
static auto fullConvertCase(char32_t uc, QUnicodeTables::Case which) noexcept
|
||||||
static FullConvertCaseResult fullConvertCase(char32_t uc, QUnicodeTables::Case which) noexcept
|
|
||||||
{
|
{
|
||||||
FullConvertCaseResult result = {};
|
struct R {
|
||||||
auto pp = result.begin();
|
char16_t chars[MaxSpecialCaseLength + 1];
|
||||||
|
qint8 sz;
|
||||||
|
|
||||||
|
// iterable
|
||||||
|
auto begin() const { return chars; }
|
||||||
|
auto end() const { return chars + sz; }
|
||||||
|
// QStringView-compatible
|
||||||
|
auto data() const { return chars; }
|
||||||
|
auto size() const { return sz; }
|
||||||
|
} result;
|
||||||
|
|
||||||
|
auto pp = result.chars;
|
||||||
|
|
||||||
const auto fold = qGetProp(uc)->cases[which];
|
const auto fold = qGetProp(uc)->cases[which];
|
||||||
const auto caseDiff = fold.diff;
|
const auto caseDiff = fold.diff;
|
||||||
@ -1609,6 +1619,7 @@ static FullConvertCaseResult fullConvertCase(char32_t uc, QUnicodeTables::Case w
|
|||||||
for (char16_t c : QChar::fromUcs4(uc + caseDiff))
|
for (char16_t c : QChar::fromUcs4(uc + caseDiff))
|
||||||
*pp++ = c;
|
*pp++ = c;
|
||||||
}
|
}
|
||||||
|
result.sz = pp - result.chars;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6148,31 +6148,27 @@ static QString detachAndConvertCase(T &str, QStringIterator it, QUnicodeTables::
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
const auto folded = fullConvertCase(it.nextUnchecked(), which);
|
const auto folded = fullConvertCase(it.nextUnchecked(), which);
|
||||||
if (Q_UNLIKELY(folded[1])) {
|
if (Q_UNLIKELY(folded.size() > 1)) {
|
||||||
if (folded[0] == *pp && !folded[2]) {
|
if (folded.chars[0] == *pp && folded.size() == 2) {
|
||||||
// special case: only second actually changed (e.g. surrogate pairs),
|
// special case: only second actually changed (e.g. surrogate pairs),
|
||||||
// avoid slow case
|
// avoid slow case
|
||||||
++pp;
|
++pp;
|
||||||
*pp++ = folded[1];
|
*pp++ = folded.chars[1];
|
||||||
} else {
|
} else {
|
||||||
// slow path: the string is growing
|
// slow path: the string is growing
|
||||||
int inpos = it.index() - 1;
|
int inpos = it.index() - 1;
|
||||||
int outpos = pp - s.constBegin();
|
int outpos = pp - s.constBegin();
|
||||||
|
|
||||||
int foldedSize = 2; // must be at least 2, b/c folded[1] != NUL
|
s.replace(outpos, 1, reinterpret_cast<const QChar *>(folded.data()), folded.size());
|
||||||
while (folded[foldedSize])
|
pp = const_cast<QChar *>(s.constBegin()) + outpos + folded.size();
|
||||||
++foldedSize;
|
|
||||||
|
|
||||||
s.replace(outpos, 1, reinterpret_cast<const QChar *>(folded.data()), foldedSize);
|
|
||||||
pp = const_cast<QChar *>(s.constBegin()) + outpos + foldedSize;
|
|
||||||
|
|
||||||
// do we need to adjust the input iterator too?
|
// do we need to adjust the input iterator too?
|
||||||
// if it is pointing to s's data, str is empty
|
// if it is pointing to s's data, str is empty
|
||||||
if (str.isEmpty())
|
if (str.isEmpty())
|
||||||
it = QStringIterator(s.constBegin(), inpos + foldedSize, s.constEnd());
|
it = QStringIterator(s.constBegin(), inpos + folded.size(), s.constEnd());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
*pp++ = folded[0];
|
*pp++ = folded.chars[0];
|
||||||
}
|
}
|
||||||
} while (it.hasNext());
|
} while (it.hasNext());
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user