summaryrefslogtreecommitdiffstats
path: root/src/corelib/text
diff options
context:
space:
mode:
authorAhmad Samir <a.samirh78@gmail.com>2022-11-27 21:18:37 +0200
committerAhmad Samir <a.samirh78@gmail.com>2023-01-31 20:02:54 +0200
commit95323397882a35bc7735a828895dcb47e5f32602 (patch)
tree2a61ff3a15e524722b56d31062b36114624663a8 /src/corelib/text
parent6b89883f6aedea5c3ec82c26f960ab98b70e23e4 (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/corelib/text')
-rw-r--r--src/corelib/text/qstring.cpp88
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;
}