QString: optimize case conversion code
Handle special case mapping of length 1 explicitly; Skip calculating of high surrogate for the same plane; Optimize branch prediction with Q_LIKELY/Q_UNLIKELY; Replace peekNext() + advance() with just next() in the caller function. Change-Id: I0d37969749bd8ca855321242e6a0e72c405c5f8d Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
7edd488a5f
commit
c3850dd636
@ -5709,37 +5709,42 @@ static QString detachAndConvertCase(T &str, QStringIterator it)
|
|||||||
Q_ASSERT(!str.isEmpty());
|
Q_ASSERT(!str.isEmpty());
|
||||||
QString s = qMove(str); // will copy if T is const QString
|
QString s = qMove(str); // will copy if T is const QString
|
||||||
QChar *pp = s.begin() + it.index(); // will detach if necessary
|
QChar *pp = s.begin() + it.index(); // will detach if necessary
|
||||||
uint uc = it.nextUnchecked();
|
|
||||||
forever {
|
do {
|
||||||
|
uint uc = it.nextUnchecked();
|
||||||
|
|
||||||
const QUnicodeTables::Properties *prop = qGetProp(uc);
|
const QUnicodeTables::Properties *prop = qGetProp(uc);
|
||||||
signed short caseDiff = Traits::caseDiff(prop);
|
signed short caseDiff = Traits::caseDiff(prop);
|
||||||
|
|
||||||
if (Q_UNLIKELY(Traits::caseSpecial(prop))) {
|
if (Q_UNLIKELY(Traits::caseSpecial(prop))) {
|
||||||
// slow path: the string is growing
|
|
||||||
const ushort *specialCase = specialCaseMap + caseDiff;
|
const ushort *specialCase = specialCaseMap + caseDiff;
|
||||||
ushort length = *specialCase++;
|
ushort length = *specialCase++;
|
||||||
int inpos = it.index() - 1;
|
|
||||||
int outpos = pp - s.constBegin();
|
|
||||||
|
|
||||||
s.replace(outpos, 1, reinterpret_cast<const QChar *>(specialCase), length);
|
if (Q_LIKELY(length == 1)) {
|
||||||
pp = const_cast<QChar *>(s.constBegin()) + outpos + length;
|
*pp++ = QChar(*specialCase);
|
||||||
|
} else {
|
||||||
|
// slow path: the string is growing
|
||||||
|
int inpos = it.index() - 1;
|
||||||
|
int outpos = pp - s.constBegin();
|
||||||
|
|
||||||
// do we need to adjust the input iterator too?
|
s.replace(outpos, 1, reinterpret_cast<const QChar *>(specialCase), length);
|
||||||
// if it is pointing to s's data, str is empty
|
pp = const_cast<QChar *>(s.constBegin()) + outpos + length;
|
||||||
if (str.isEmpty())
|
|
||||||
it = QStringIterator(s.constBegin(), inpos + length, s.constEnd());
|
// do we need to adjust the input iterator too?
|
||||||
} else if (QChar::requiresSurrogates(uc)) {
|
// if it is pointing to s's data, str is empty
|
||||||
*pp++ = QChar::highSurrogate(uc + caseDiff);
|
if (str.isEmpty())
|
||||||
|
it = QStringIterator(s.constBegin(), inpos + length, s.constEnd());
|
||||||
|
}
|
||||||
|
} else if (Q_UNLIKELY(QChar::requiresSurrogates(uc))) {
|
||||||
|
// so far, case convertion never changes planes (guaranteed by the qunicodetables generator)
|
||||||
|
pp++;
|
||||||
*pp++ = QChar::lowSurrogate(uc + caseDiff);
|
*pp++ = QChar::lowSurrogate(uc + caseDiff);
|
||||||
} else {
|
} else {
|
||||||
*pp++ = QChar(uc + caseDiff);
|
*pp++ = QChar(uc + caseDiff);
|
||||||
}
|
}
|
||||||
|
} while (it.hasNext());
|
||||||
|
|
||||||
if (!it.hasNext())
|
return s;
|
||||||
return s;
|
|
||||||
|
|
||||||
uc = it.nextUnchecked();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Traits, typename T>
|
template <typename Traits, typename T>
|
||||||
@ -5752,12 +5757,13 @@ static QString convertCase(T &str)
|
|||||||
while (e != p && e[-1].isHighSurrogate())
|
while (e != p && e[-1].isHighSurrogate())
|
||||||
--e;
|
--e;
|
||||||
|
|
||||||
const QUnicodeTables::Properties *prop;
|
|
||||||
QStringIterator it(p, e);
|
QStringIterator it(p, e);
|
||||||
for ( ; it.hasNext(); it.advanceUnchecked()) {
|
while (it.hasNext()) {
|
||||||
prop = qGetProp(it.peekNextUnchecked());
|
uint uc = it.nextUnchecked();
|
||||||
if (Traits::caseDiff(prop))
|
if (Traits::caseDiff(qGetProp(uc))) {
|
||||||
|
it.recedeUnchecked();
|
||||||
return detachAndConvertCase<Traits>(str, it);
|
return detachAndConvertCase<Traits>(str, it);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return qMove(str);
|
return qMove(str);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user