diff options
author | Ahmad Samir <a.samirh78@gmail.com> | 2022-12-14 23:53:57 +0200 |
---|---|---|
committer | Ahmad Samir <a.samirh78@gmail.com> | 2023-02-09 16:49:26 +0200 |
commit | cc6324665eb61eca136e9057ce1c72a2a0c32d31 (patch) | |
tree | 8d3cba09bd0f9da5f95c0abb4eaf43f1c34c0023 /src/corelib/text | |
parent | 67108ef8db0b134908a88e2da7a533be98f0c796 (diff) |
QString: don't detach in insert()
Instead of detaching when the string is shared, or if the the insertion
would cause a reallocation, create a new string and copy characters to
it as needed, then swap it with "this" string. This is more efficient
than detaching which would copy the whole string before inserting, as
some characters would be copied multiple times.
Use detachAndGrow(), otherwise QStringBuilder unitests fail:
PASS : tst_QStringBuilder1::initTestCase()
FAIL! : tst_QStringBuilder1::scenario() 'prepends < max_prepends' returned FALSE. ()
Loc: [tests/auto/corelib/text/qstringbuilder/qstringbuilder1/stringbuilder.cpp(61)]
PASS : tst_QStringBuilder1::cleanupTestCase()
The issue is that now when inserting, if the string is going to
reallocated, we create a new string, so the freeSpaceAtBegin()
optimization doesn't work the same way.
void checkItWorksWithFreeSpaceAtBegin(const String &chunk, const Separator &separator)
{
// GIVEN: a String with freeSpaceAtBegin() and less than chunk.size() freeSpaceAtEnd()
String str;
int prepends = 0;
const int max_prepends = 10;
while (str.data_ptr().freeSpaceAtBegin() < chunk.size() && prepends++ < max_prepends)
str.prepend(chunk);
QVERIFY(prepends < max_prepends);
...
...
each str.prepend() would have reallocated.
[ChangeLog][QtCore][QString] Calling insert() on a currently shared
string is now done more efficiently.
Task-number: QTBUG-106186
Change-Id: I07ce8d6bde50919fdc587433e624ace9cee05be8
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/text')
-rw-r--r-- | src/corelib/text/qstring.cpp | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp index 305d6e9a67..daa8f8d98b 100644 --- a/src/corelib/text/qstring.cpp +++ b/src/corelib/text/qstring.cpp @@ -2951,6 +2951,23 @@ static void insert_helper(QString &str, qsizetype i, T toInsert) const qsizetype insert_size = toInsert.size(); const qsizetype newSize = str_d.size + difference + insert_size; const auto side = i == 0 ? QArrayData::GrowsAtBeginning : QArrayData::GrowsAtEnd; + + if (str_d.needsDetach() || needsReallocate(str, newSize)) { + const auto cbegin = str.cbegin(); + const auto cend = str.cend(); + const auto insert_start = difference == 0 ? std::next(cbegin, i) : cend; + QString other; + // Using detachAndGrow() so that prepend optimization works and QStringBuilder + // unittests pass + other.data_ptr().detachAndGrow(side, newSize, nullptr, nullptr); + other.append(QStringView(cbegin, insert_start)); + other.resize(i, u' '); + other.append(toInsert); + other.append(QStringView(insert_start, cend)); + str.swap(other); + return; + } + str_d.detachAndGrow(side, difference + insert_size, nullptr, nullptr); Q_CHECK_PTR(str_d.data()); str.resize(newSize); |