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 performAVN = false,
|
||||||
const bool encodeEOLs = false)
|
const bool encodeEOLs = false)
|
||||||
{
|
{
|
||||||
QString retval(str);
|
QString retval;
|
||||||
int len = retval.size();
|
qsizetype start = 0;
|
||||||
int i = 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 qsizetype len = str.size();
|
||||||
const QChar ati(retval.at(i));
|
for (qsizetype cur = 0; cur < len; ++cur) {
|
||||||
|
switch (str[cur].unicode()) {
|
||||||
if (ati == u'<') {
|
case u'<':
|
||||||
retval.replace(i, 1, "<"_L1);
|
appendToOutput(cur, "<"_L1);
|
||||||
len += 3;
|
break;
|
||||||
i += 4;
|
case u'"':
|
||||||
} else if (encodeQuotes && (ati == u'"')) {
|
if (encodeQuotes)
|
||||||
retval.replace(i, 1, """_L1);
|
appendToOutput(cur, """_L1);
|
||||||
len += 5;
|
break;
|
||||||
i += 6;
|
case u'&':
|
||||||
} else if (ati == u'&') {
|
appendToOutput(cur, "&"_L1);
|
||||||
retval.replace(i, 1, "&"_L1);
|
break;
|
||||||
len += 4;
|
case u'>':
|
||||||
i += 5;
|
if (cur >= 2 && str[cur - 1] == u']' && str[cur - 2] == u']')
|
||||||
} else if (ati == u'>' && i >= 2 && retval[i - 1] == u']' && retval[i - 2] == u']') {
|
appendToOutput(cur, ">"_L1);
|
||||||
retval.replace(i, 1, ">"_L1);
|
break;
|
||||||
len += 3;
|
case u'\r':
|
||||||
i += 4;
|
if (performAVN || encodeEOLs)
|
||||||
} else if (performAVN &&
|
appendToOutput(cur, "
"_L1); // \r == 0x0d
|
||||||
(ati == QChar(0xA) ||
|
break;
|
||||||
ati == QChar(0xD) ||
|
case u'\n':
|
||||||
ati == QChar(0x9))) {
|
if (performAVN)
|
||||||
const QString replacement(u"&#x"_s + QString::number(ati.unicode(), 16) + u';');
|
appendToOutput(cur, "
"_L1); // \n == 0x0a
|
||||||
retval.replace(i, 1, replacement);
|
break;
|
||||||
i += replacement.size();
|
case u'\t':
|
||||||
len += replacement.size() - 1;
|
if (performAVN)
|
||||||
} else if (encodeEOLs && ati == QChar(0xD)) {
|
appendToOutput(cur, "	"_L1); // \t == 0x09
|
||||||
retval.replace(i, 1, "
"_L1); // Replace a single 0xD with a ref for 0xD
|
break;
|
||||||
len += 4;
|
default:
|
||||||
i += 5;
|
break;
|
||||||
} else {
|
|
||||||
++i;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (start > 0) {
|
||||||
|
retval.append(QStringView(str).first(len).sliced(start));
|
||||||
return retval;
|
return retval;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QDomAttrPrivate::save(QTextStream& s, int, int) const
|
void QDomAttrPrivate::save(QTextStream& s, int, int) const
|
||||||
|
Loading…
x
Reference in New Issue
Block a user