diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp index daa8f8d98b..b6c36e1b2f 100644 --- a/src/corelib/text/qstring.cpp +++ b/src/corelib/text/qstring.cpp @@ -2939,7 +2939,9 @@ QString &QString::operator=(QChar ch) defined. */ - +/*! \internal + T is a view or a container on/of QChar, char16_t, or char +*/ template static void insert_helper(QString &str, qsizetype i, T toInsert) { @@ -3021,7 +3023,32 @@ QString &QString::insert(qsizetype i, QLatin1StringView str) */ QString &QString::insert(qsizetype i, QUtf8StringView s) { - return insert(i, s.toString()); // ### optimize (QTBUG-108546) + auto insert_size = s.size(); + if (i < 0 || insert_size <= 0) + return *this; + + qsizetype difference = 0; + if (Q_UNLIKELY(i > d.size)) + difference = i - d.size; + + if (i >= d.size) { + d.detachAndGrow(QArrayData::GrowsAtEnd, difference + insert_size, nullptr, nullptr); + Q_CHECK_PTR(d.data()); + + if (difference > 0) + resize(i, u' '); + append(s); + } else { + // Optimal insertion of Utf8 data is at the end, anywhere else could + // potentially lead to moving characters twice if Utf8 data size + // (variable-width) is less than the equiavalent Utf16 data size + QVarLengthArray buffer(insert_size); // ### optimize (QTBUG-108546) + char16_t *b = QUtf8::convertToUnicode(buffer.data(), s); + buffer.resize(std::distance(buffer.begin(), b)); + insert_helper(*this, i, buffer); + } + + return *this; } /*! diff --git a/tests/auto/corelib/text/qstring/tst_qstring.cpp b/tests/auto/corelib/text/qstring/tst_qstring.cpp index ac3d4d0f85..ca20e2fe5a 100644 --- a/tests/auto/corelib/text/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/text/qstring/tst_qstring.cpp @@ -2803,6 +2803,7 @@ void tst_QString::insert_data(DataOptions options) QTest::newRow("a.insert(1, ba)") << a << baC << 1 << (a + ba); QTest::newRow("ba.insert(1, a)") << ba << aC << 1 << (ba + a); QTest::newRow("ba.insert(2, b)") << ba << bC << 2 << (ba + b); + QTest::newRow("ba.insert(10, b)") << ba << bC << 10 << (ba + QString(10 - ba.size(), u' ') + b); QTest::newRow("null-insert-0-yumlaut") << null << yumlautC << 0 << yumlaut; QTest::newRow("empty-insert-0-yumlaut") << empty << yumlautC << 0 << yumlaut;