128 lines
4.5 KiB
Diff
128 lines
4.5 KiB
Diff
From 905a5bd421efff6a1d90b6140500d134d32ca745 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.
|
|
|
|
Manual conflict resolution for 6.5:
|
|
- This is a manual cherry-pick. The original change was only
|
|
picked to 6.8, but the quadratic behavior is present in Qt 5, too.
|
|
- Changed Task-number to Fixes: because this is the real fix;
|
|
the QString change, 315210de916d060c044c01e53ff249d676122b1b,
|
|
was unrelated to the original QTBUG-127549.
|
|
|
|
Pick-to: 5.15
|
|
Fixes: 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>
|
|
(cherry picked from commit 225e235cf966a44af23dbe9aaaa2fd20ab6430ee)
|
|
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
|
|
---
|
|
|
|
diff --git a/src/xml/dom/qdom.cpp b/src/xml/dom/qdom.cpp
|
|
index 7b45237..45cde91 100644
|
|
--- a/src/xml/dom/qdom.cpp
|
|
+++ b/src/xml/dom/qdom.cpp
|
|
@@ -3607,47 +3607,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
|