From 95323397882a35bc7735a828895dcb47e5f32602 Mon Sep 17 00:00:00 2001 From: Ahmad Samir Date: Sun, 27 Nov 2022 21:18:37 +0200 Subject: QString: use QVLA instead of built-in array This simplifies the code as a QVLA's size isn't limited to 1024. Also it allows the code to allocate a big enough buffer to hold the result, i.e. no reallocations. insert_helper() takes care of storing a copy of "after" if it points into "this" string; and "before" pointing into "this" isn't an issue since we collected the indices before starting the replacement. Change-Id: I612948187226439349118e65e9525ded2b387da0 Reviewed-by: Thiago Macieira Reviewed-by: Marc Mutz --- src/corelib/text/qstring.cpp | 88 ++++++++++++-------------------------------- 1 file changed, 24 insertions(+), 64 deletions(-) (limited to 'src/corelib/text') diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp index 58bba15a05..c50b7e967b 100644 --- a/src/corelib/text/qstring.cpp +++ b/src/corelib/text/qstring.cpp @@ -3677,49 +3677,21 @@ QString &QString::replace(const QChar *before, qsizetype blen, return replace(*before, *after, cs); QStringMatcher matcher(before, blen, cs); - QChar *beforeBuffer = nullptr, *afterBuffer = nullptr; qsizetype index = 0; - while (1) { - size_t indices[1024]; - size_t pos = 0; - while (pos < 1024) { - index = matcher.indexIn(*this, index); - if (index == -1) - break; - indices[pos++] = index; - if (blen) // Step over before: - index += blen; - else // Only count one instance of empty between any two characters: - index++; - } - if (!pos) // Nothing to replace - break; - - if (Q_UNLIKELY(index != -1)) { - /* - We're about to change data, that before and after might point - into, and we'll need that data for our next batch of indices. - */ - if (!afterBuffer && QtPrivate::q_points_into_range(after, *this)) - after = afterBuffer = textCopy(after, alen); - - if (!beforeBuffer && QtPrivate::q_points_into_range(before, *this)) { - beforeBuffer = textCopy(before, blen); - matcher = QStringMatcher(beforeBuffer, blen, cs); - } - } - replace_helper(*this, indices, pos, blen, after, alen); - - if (Q_LIKELY(index == -1)) // Nothing left to replace - break; - // The call to replace_helper just moved what index points at: - index += pos*(alen-blen); + QVarLengthArray indices; + while ((index = matcher.indexIn(*this, index)) != -1) { + indices.push_back(index); + if (blen) // Step over before: + index += blen; + else // Only count one instance of empty between any two characters: + index++; } - ::free(afterBuffer); - ::free(beforeBuffer); + if (indices.isEmpty()) + return *this; + replace_helper(*this, indices.data(), indices.size(), blen, after, alen); return *this; } @@ -3741,35 +3713,23 @@ QString& QString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs if (size() == 0) return *this; - char16_t cc = (cs == Qt::CaseSensitive ? ch.unicode() : ch.toCaseFolded().unicode()); + const char16_t cc = (cs == Qt::CaseSensitive ? ch.unicode() : ch.toCaseFolded().unicode()); - qsizetype index = 0; - while (1) { - size_t indices[1024]; - size_t pos = 0; - if (cs == Qt::CaseSensitive) { - while (pos < 1024 && index < size()) { - if (d.data()[index] == cc) - indices[pos++] = index; - index++; - } - } else { - while (pos < 1024 && index < size()) { - if (QChar::toCaseFolded(d.data()[index]) == cc) - indices[pos++] = index; - index++; - } - } - if (!pos) // Nothing to replace - break; + QVarLengthArray indices; + if (cs == Qt::CaseSensitive) { + for (qsizetype i = 0; i < d.size; ++i) + if (d.data()[i] == cc) + indices.push_back(i); + } else { + for (qsizetype i = 0; i < d.size; ++i) + if (QChar::toCaseFolded(d.data()[i]) == cc) + indices.push_back(i); + } - replace_helper(*this, indices, pos, 1, after.constData(), after.size()); + if (indices.isEmpty()) + return *this; - if (Q_LIKELY(index == size())) // Nothing left to replace - break; - // The call to replace_helper just moved what index points at: - index += pos*(after.size() - 1); - } + replace_helper(*this, indices.data(), indices.size(), 1, after.constData(), after.size()); return *this; } -- cgit v1.2.3