XML/QDom: speedup encodeText()
The code copied the whole string, then replaced parts inline, at the cost of relocating everything beyond, at each replacement. Instead, copy character by character (in chunks where possible) and append replacements as we skip what they replace. Task-number: QTBUG-127549 Change-Id: I368482859ed0c4127f1eec2919183711b5488ada Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> (cherry picked from commit 2ce08e3671b8d18b0284447e5908ce15e6e8f80f) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
e0b2258b03
commit
225e235cf9
@ -3611,47 +3611,57 @@ static QString encodeText(const QString &str,
|
||||
const bool performAVN = false,
|
||||
const bool encodeEOLs = false)
|
||||
{
|
||||
QString retval(str);
|
||||
int len = retval.size();
|
||||
int i = 0;
|
||||
QString retval;
|
||||
qsizetype start = 0;
|
||||
auto appendToOutput = [&](qsizetype cur, const auto &replacement)
|
||||
{
|
||||
if (start < cur) {
|
||||
retval.reserve(str.size() + replacement.size());
|
||||
retval.append(QStringView(str).first(cur).sliced(start));
|
||||
}
|
||||
// Skip over str[cur], replaced by replacement
|
||||
start = cur + 1;
|
||||
retval.append(replacement);
|
||||
};
|
||||
|
||||
while (i < len) {
|
||||
const QChar ati(retval.at(i));
|
||||
|
||||
if (ati == u'<') {
|
||||
retval.replace(i, 1, "<"_L1);
|
||||
len += 3;
|
||||
i += 4;
|
||||
} else if (encodeQuotes && (ati == u'"')) {
|
||||
retval.replace(i, 1, """_L1);
|
||||
len += 5;
|
||||
i += 6;
|
||||
} else if (ati == u'&') {
|
||||
retval.replace(i, 1, "&"_L1);
|
||||
len += 4;
|
||||
i += 5;
|
||||
} else if (ati == u'>' && i >= 2 && retval[i - 1] == u']' && retval[i - 2] == u']') {
|
||||
retval.replace(i, 1, ">"_L1);
|
||||
len += 3;
|
||||
i += 4;
|
||||
} else if (performAVN &&
|
||||
(ati == QChar(0xA) ||
|
||||
ati == QChar(0xD) ||
|
||||
ati == QChar(0x9))) {
|
||||
const QString replacement(u"&#x"_s + QString::number(ati.unicode(), 16) + u';');
|
||||
retval.replace(i, 1, replacement);
|
||||
i += replacement.size();
|
||||
len += replacement.size() - 1;
|
||||
} else if (encodeEOLs && ati == QChar(0xD)) {
|
||||
retval.replace(i, 1, "
"_L1); // Replace a single 0xD with a ref for 0xD
|
||||
len += 4;
|
||||
i += 5;
|
||||
} else {
|
||||
++i;
|
||||
const qsizetype len = str.size();
|
||||
for (qsizetype cur = 0; cur < len; ++cur) {
|
||||
switch (str[cur].unicode()) {
|
||||
case u'<':
|
||||
appendToOutput(cur, "<"_L1);
|
||||
break;
|
||||
case u'"':
|
||||
if (encodeQuotes)
|
||||
appendToOutput(cur, """_L1);
|
||||
break;
|
||||
case u'&':
|
||||
appendToOutput(cur, "&"_L1);
|
||||
break;
|
||||
case u'>':
|
||||
if (cur >= 2 && str[cur - 1] == u']' && str[cur - 2] == u']')
|
||||
appendToOutput(cur, ">"_L1);
|
||||
break;
|
||||
case u'\r':
|
||||
if (performAVN || encodeEOLs)
|
||||
appendToOutput(cur, "
"_L1); // \r == 0x0d
|
||||
break;
|
||||
case u'\n':
|
||||
if (performAVN)
|
||||
appendToOutput(cur, "
"_L1); // \n == 0x0a
|
||||
break;
|
||||
case u'\t':
|
||||
if (performAVN)
|
||||
appendToOutput(cur, "	"_L1); // \t == 0x09
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
if (start > 0) {
|
||||
retval.append(QStringView(str).first(len).sliced(start));
|
||||
return retval;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
void QDomAttrPrivate::save(QTextStream& s, int, int) const
|
||||
|
Loading…
x
Reference in New Issue
Block a user