File 0001-XML-QDom-speedup-encodeText.patch of Package qt6-base.40448
From 225e235cf966a44af23dbe9aaaa2fd20ab6430ee Mon Sep 17 00:00:00 2001
From: Christian Ehrlicher <ch.ehrlicher@gmx.de>
Date: Tue, 06 Aug 2024 22:39:44 +0200
Subject: [PATCH] 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>
---
diff --git a/src/xml/dom/qdom.cpp b/src/xml/dom/qdom.cpp
index b25cdf4..a9c2a64 100644
--- a/src/xml/dom/qdom.cpp
+++ b/src/xml/dom/qdom.cpp
@@ -3611,47 +3611,57 @@
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