diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp index 4d7522a2b8..fd341e7139 100644 --- a/src/corelib/text/qstring.cpp +++ b/src/corelib/text/qstring.cpp @@ -3294,9 +3294,22 @@ QString &QString::remove(qsizetype pos, qsizetype len) return *this; len = std::min(len, size() - pos); - detach(); - d->erase(d.begin() + pos, len); - d.data()[d.size] = u'\0'; + + if (!d->isShared()) { + d->erase(d.begin() + pos, len); + d.data()[d.size] = u'\0'; + } else { + // TODO: either reserve "size()", which is bigger than needed, or + // modify the shrinking-erase docs of this method (since the size + // of "copy" won't have any extra capacity any more) + const qsizetype sz = size() - len; + QString copy{sz, Qt::Uninitialized}; + auto begin = d.begin(); + auto toRemove_start = d.begin() + pos; + copy.d->copyRanges({{begin, toRemove_start}, + {toRemove_start + len, d.end()}}); + swap(copy); + } return *this; } diff --git a/src/corelib/tools/qarraydataops.h b/src/corelib/tools/qarraydataops.h index afd1a264bd..13d5572c03 100644 --- a/src/corelib/tools/qarraydataops.h +++ b/src/corelib/tools/qarraydataops.h @@ -213,6 +213,17 @@ public: --this->size; } + struct Span { T *begin; T *end; }; + + void copyRanges(const std::initializer_list &ranges) + { + auto it = this->begin(); + std::for_each(ranges.begin(), ranges.end(), [&it](const auto &span) { + it = std::copy(span.begin, span.end, it); + }); + this->size = std::distance(this->begin(), it); + } + void assign(T *b, T *e, parameter_type t) noexcept { Q_ASSERT(b <= e); diff --git a/tests/auto/corelib/text/qstring/tst_qstring.cpp b/tests/auto/corelib/text/qstring/tst_qstring.cpp index 80bc6c9208..0462d0689d 100644 --- a/tests/auto/corelib/text/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/text/qstring/tst_qstring.cpp @@ -3318,13 +3318,23 @@ void tst_QString::remove_uint_uint() QFETCH( int, index ); QFETCH( int, len ); QFETCH( QString, after ); + QFETCH(QString, result); - if ( after.size() == 0 ) { - QString s1 = string; - s1.remove( (uint) index, (uint) len ); - QTEST( s1, "result" ); - } else - QCOMPARE( 0, 0 ); // shut Qt Test + // For the replace() unitests? + if ( after.size() != 0 ) { + return; + } + + // Test when isShared() is true + QString s1 = string; + s1.remove((qsizetype)index, (qsizetype)len); + QCOMPARE(s1, result); + + QString s2 = string; + // Test when isShared() is false + s2.detach(); + s2.remove((qsizetype)index, (qsizetype)len); + QCOMPARE(s2, result); } void tst_QString::remove_string()