optimize QString::toCaseFolded()

use the codepath similar to QString::toLower()

Change-Id: Ica1948c5e9c82199307d9f823e07d42b50d59480
Merge-request: 70
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@nokia.com>
Reviewed-by: Olivier
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
This commit is contained in:
Konstantin Ritt 2011-10-18 19:12:19 +02:00 committed by Qt by Nokia
parent 34be7e1625
commit 20faf6408a

View File

@ -4950,31 +4950,51 @@ QString QString::toLower() const
*/ */
QString QString::toCaseFolded() const QString QString::toCaseFolded() const
{ {
if (!d->size)
return *this;
const ushort *p = d->data(); const ushort *p = d->data();
if (!p) if (!p)
return *this; return *this;
const ushort *e = d->data() + d->size; const ushort *e = p + d->size;
// this avoids out of bounds check in the loop
while (e != p && QChar::isHighSurrogate(*(e - 1)))
--e;
uint last = 0; const QUnicodeTables::Properties *prop;
while (p < e) { while (p != e) {
ushort folded = foldCase(*p, last); if (QChar::isHighSurrogate(*p) && QChar::isLowSurrogate(p[1])) {
if (folded != *p) { ushort high = *p++;
QString s(*this); prop = qGetProp(QChar::surrogateToUcs4(high, *p));
s.detach(); } else {
ushort *pp = s.d->data() + (p - d->data()); prop = qGetProp(*p);
const ushort *ppe = s.d->data() + s.d->size;
last = pp > s.d->data() ? *(pp - 1) : 0;
while (pp < ppe) {
*pp = foldCase(*pp, last);
++pp;
} }
if (prop->caseFoldDiff || prop->caseFoldSpecial) {
if (QChar::isLowSurrogate(*p))
--p; // safe; diff is 0 for surrogates
QString s(d->size, Qt::Uninitialized);
memcpy(s.d->data(), d->data(), (p - d->data())*sizeof(ushort));
ushort *pp = s.d->data() + (p - d->data());
while (p != e) {
if (QChar::isHighSurrogate(*p) && QChar::isLowSurrogate(p[1])) {
*pp = *p++;
prop = qGetProp(QChar::surrogateToUcs4(*pp++, *p));
} else {
prop = qGetProp(*p);
}
if (prop->caseFoldSpecial) {
//### we currently don't support full case foldings
} else {
*pp++ = *p + prop->caseFoldDiff;
}
++p;
}
// this restores high surrogate parts eaten above, if any
while (e != d->data() + d->size)
*pp++ = *e++;
return s; return s;
} }
p++; ++p;
} }
return *this; return *this;
} }