summaryrefslogtreecommitdiffstats
path: root/src/corelib/text
diff options
context:
space:
mode:
authorAndrei Golubev <andrei.golubev@qt.io>2021-03-24 16:47:33 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-04-27 07:39:49 +0000
commit8e95bba272bc2aadc2e2dd4ad66dab489cb70387 (patch)
tree3c07b75d4b9460e4e26e9d1b37c88a682f389127 /src/corelib/text
parentad496ea3b5ae79172af3a0231a65ae7c7ee44492 (diff)
Resurrect data moves in QList
Use the data moves to readjust the free space in the QList, which ultimately fixes the out-of-memory issues caused by cases like: forever { list.prepend(list.back()); list.removeLast(); } Task-number: QTBUG-91801 Task-number: QTBUG-91360 Task-number: QTBUG-93019 Change-Id: Iacff69cbf36b8b5b176bb2663df635ec972c875c Reviewed-by: Lars Knoll <lars.knoll@qt.io> (cherry picked from commit a0253f5f0249024580050e4ec22d50cb139ef8d9) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src/corelib/text')
-rw-r--r--src/corelib/text/qbytearray.cpp19
-rw-r--r--src/corelib/text/qstring.cpp49
2 files changed, 27 insertions, 41 deletions
diff --git a/src/corelib/text/qbytearray.cpp b/src/corelib/text/qbytearray.cpp
index 045d8a73b4..23e295405f 100644
--- a/src/corelib/text/qbytearray.cpp
+++ b/src/corelib/text/qbytearray.cpp
@@ -1956,8 +1956,7 @@ QByteArray &QByteArray::append(const QByteArray &ba)
QByteArray& QByteArray::append(char ch)
{
- if (d->needsDetach() || !d->freeSpaceAtEnd())
- reallocGrowData(1);
+ d.detachAndGrow(QArrayData::GrowsAtEnd, 1, nullptr, nullptr);
d->copyAppend(1, ch);
d.data()[d.size] = '\0';
return *this;
@@ -1997,12 +1996,8 @@ QByteArray &QByteArray::insert(qsizetype i, QByteArrayView data)
// defer a call to free() so that it comes after we copied the data from
// the old memory:
DataPointer detached{}; // construction is free
- if (d->needsDetach() || i + size - d->size > d.freeSpaceAtEnd()) {
- detached = DataPointer::allocateGrow(d, i + size - d->size, Data::GrowsAtEnd);
- Q_CHECK_PTR(detached.data());
- detached->copyAppend(d.constBegin(), d.constEnd());
- d.swap(detached);
- }
+ d.detachAndGrow(Data::GrowsAtEnd, (i - d.size) + size, &str, &detached);
+ Q_CHECK_PTR(d.data());
d->copyAppend(i - d->size, ' ');
d->copyAppend(str, str + size);
d.data()[d.size] = '\0';
@@ -2079,12 +2074,8 @@ QByteArray &QByteArray::insert(qsizetype i, qsizetype count, char ch)
if (i >= d->size) {
// handle this specially, as QArrayDataOps::insert() doesn't handle out of bounds positions
- if (d->needsDetach() || i + count - d->size > d.freeSpaceAtEnd()) {
- DataPointer detached(DataPointer::allocateGrow(d, i + count - d->size, Data::GrowsAtEnd));
- Q_CHECK_PTR(detached.data());
- detached->copyAppend(d.constBegin(), d.constEnd());
- d.swap(detached);
- }
+ d.detachAndGrow(Data::GrowsAtEnd, (i - d.size) + count, nullptr, nullptr);
+ Q_CHECK_PTR(d.data());
d->copyAppend(i - d->size, ' ');
d->copyAppend(count, ch);
d.data()[d.size] = '\0';
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp
index c2af431c94..89957e5cb6 100644
--- a/src/corelib/text/qstring.cpp
+++ b/src/corelib/text/qstring.cpp
@@ -2760,13 +2760,17 @@ QString &QString::insert(qsizetype i, QLatin1String str)
return *this;
qsizetype len = str.size();
+ qsizetype difference = 0;
if (Q_UNLIKELY(i > size()))
- resize(i + len, QLatin1Char(' '));
- else
- resize(size() + len);
+ difference = i - size();
+ d.detachAndGrow(Data::GrowsAtEnd, difference + len, nullptr, nullptr);
+ Q_CHECK_PTR(d.data());
+ d->copyAppend(difference, u' ');
+ d.size += len;
::memmove(d.data() + i + len, d.data() + i, (d.size - i - len) * sizeof(QChar));
qt_from_latin1(d.data() + i, s, size_t(len));
+ d.data()[d.size] = u'\0';
return *this;
}
@@ -2787,7 +2791,7 @@ QString& QString::insert(qsizetype i, const QChar *unicode, qsizetype size)
if (i < 0 || size <= 0)
return *this;
- const auto s = reinterpret_cast<const char16_t *>(unicode);
+ const char16_t *s = reinterpret_cast<const char16_t *>(unicode);
// handle this specially, as QArrayDataOps::insert() doesn't handle out of
// bounds positions
@@ -2796,12 +2800,8 @@ QString& QString::insert(qsizetype i, const QChar *unicode, qsizetype size)
// defer a call to free() so that it comes after we copied the data from
// the old memory:
DataPointer detached{}; // construction is free
- if (d->needsDetach() || i + size - d->size > d.freeSpaceAtEnd()) {
- detached = DataPointer::allocateGrow(d, i + size - d->size, Data::GrowsAtEnd);
- Q_CHECK_PTR(detached.data());
- detached->copyAppend(d.constBegin(), d.constEnd());
- d.swap(detached);
- }
+ d.detachAndGrow(Data::GrowsAtEnd, (i - d.size) + size, &s, &detached);
+ Q_CHECK_PTR(d.data());
d->copyAppend(i - d->size, u' ');
d->copyAppend(s, s + size);
d.data()[d.size] = u'\0';
@@ -2857,11 +2857,8 @@ QString &QString::append(const QString &str)
if (!str.isNull()) {
if (isNull()) {
operator=(str);
- } else {
- if (d->needsDetach() || str.size() > d->freeSpaceAtEnd())
- reallocGrowData(str.size());
- d->copyAppend(str.d.data(), str.d.data() + str.d.size);
- d.data()[d.size] = '\0';
+ } else if (str.size()) {
+ append(str.constData(), str.size());
}
}
return *this;
@@ -2876,13 +2873,11 @@ QString &QString::append(const QString &str)
QString &QString::append(const QChar *str, qsizetype len)
{
if (str && len > 0) {
- if (d->needsDetach() || len > d->freeSpaceAtEnd())
- reallocGrowData(len);
static_assert(sizeof(QChar) == sizeof(char16_t), "Unexpected difference in sizes");
// the following should be safe as QChar uses char16_t as underlying data
const char16_t *char16String = reinterpret_cast<const char16_t *>(str);
- d->copyAppend(char16String, char16String + len);
- d.data()[d.size] = '\0';
+ d->growAppend(char16String, char16String + len);
+ d.data()[d.size] = u'\0';
}
return *this;
}
@@ -2895,16 +2890,17 @@ QString &QString::append(const QChar *str, qsizetype len)
QString &QString::append(QLatin1String str)
{
const char *s = str.latin1();
- if (s) {
- qsizetype len = str.size();
- if (d->needsDetach() || str.size() > d->freeSpaceAtEnd())
- reallocGrowData(len);
-
- Q_ASSERT(str.size() <= d->freeSpaceAtEnd());
+ const qsizetype len = str.size();
+ if (s && len > 0) {
+ d.detachAndGrow(Data::GrowsAtEnd, len, nullptr, nullptr);
+ Q_CHECK_PTR(d.data());
+ Q_ASSERT(len <= d->freeSpaceAtEnd());
char16_t *i = d.data() + d.size;
qt_from_latin1(i, s, size_t(len));
d.size += len;
d.data()[d.size] = '\0';
+ } else if (d.isNull() && !str.isNull()) { // special case
+ d = DataPointer::fromRawData(&_empty, 0);
}
return *this;
}
@@ -2942,8 +2938,7 @@ QString &QString::append(QLatin1String str)
*/
QString &QString::append(QChar ch)
{
- if (d->needsDetach() || !d->freeSpaceAtEnd())
- reallocGrowData(1);
+ d.detachAndGrow(QArrayData::GrowsAtEnd, 1, nullptr, nullptr);
d->copyAppend(1, ch.unicode());
d.data()[d.size] = '\0';
return *this;