summaryrefslogtreecommitdiffstats
path: root/src/corelib/text
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/text')
-rw-r--r--src/corelib/text/qstring.cpp52
1 files changed, 28 insertions, 24 deletions
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp
index 381ae8e6fd..5d56c586c9 100644
--- a/src/corelib/text/qstring.cpp
+++ b/src/corelib/text/qstring.cpp
@@ -2954,18 +2954,22 @@ QString &QString::insert(qsizetype i, QLatin1StringView str)
if (i < 0 || !s || !(*s))
return *this;
- qsizetype len = str.size();
+ const qsizetype len = str.size();
qsizetype difference = 0;
if (Q_UNLIKELY(i > size()))
difference = i - size();
+ const qsizetype oldSize = d.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';
+ resize(d.size + difference + len);
+
+ auto begin = d.data();
+ auto old_end = std::next(begin, oldSize);
+ std::fill_n(old_end, difference, u' ');
+ auto insert_start = std::next(begin, i);
+ if (difference == 0)
+ std::move_backward(insert_start, old_end, d.end());
+ qt_from_latin1(insert_start, s, len);
return *this;
}
@@ -3006,26 +3010,26 @@ QString& QString::insert(qsizetype i, const QChar *unicode, qsizetype size)
const char16_t *s = reinterpret_cast<const char16_t *>(unicode);
- // handle this specially, as QArrayDataOps::insert() doesn't handle out of
- // bounds positions
- if (i >= d->size) {
- // In case when data points into the range or is == *this, we need to
- // defer a call to free() so that it comes after we copied the data from
- // the old memory:
- DataPointer detached{}; // construction is free
- 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';
- return *this;
- }
-
+ // In case when data points into "this"
if (!d->needsDetach() && QtPrivate::q_points_into_range(s, d))
return insert(i, QStringView{QVarLengthArray(s, s + size)});
- d->insert(i, s, size);
- d.data()[d.size] = u'\0';
+ const qsizetype difference = i > d.size ? i - d.size : 0;
+ const qsizetype oldSize = d.size;
+ const qsizetype newSize = d.size + difference + size;
+ const auto side = i == 0 ? Data::GrowsAtBeginning : Data::GrowsAtEnd;
+ d.detachAndGrow(side, difference + size, nullptr, nullptr);
+ Q_CHECK_PTR(d.data());
+ resize(newSize);
+
+ auto begin = d.begin();
+ auto old_end = std::next(begin, oldSize);
+ std::fill_n(old_end, difference, u' ');
+ auto insert_start = std::next(begin, i);
+ if (difference == 0)
+ std::move_backward(insert_start, old_end, d.end());
+ std::copy_n(s, size, insert_start);
+
return *this;
}