diff options
author | Ahmad Samir <a.samirh78@gmail.com> | 2022-11-27 21:18:37 +0200 |
---|---|---|
committer | Ahmad Samir <a.samirh78@gmail.com> | 2023-01-31 20:02:54 +0200 |
commit | 95323397882a35bc7735a828895dcb47e5f32602 (patch) | |
tree | 2a61ff3a15e524722b56d31062b36114624663a8 /src | |
parent | 6b89883f6aedea5c3ec82c26f960ab98b70e23e4 (diff) |
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 <thiago.macieira@intel.com>
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/text/qstring.cpp | 88 |
1 files changed, 24 insertions, 64 deletions
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<size_t> 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<size_t> 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; } |