diff --git a/src/xml/dom/qdom.cpp b/src/xml/dom/qdom.cpp index b25cdf487fc..a9c2a648582 100644 --- a/src/xml/dom/qdom.cpp +++ b/src/xml/dom/qdom.cpp @@ -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